From 422d4bf8cd0b021a20350f0ee63addeaf89d05f4 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Sun, 17 Dec 2023 18:05:17 +0100 Subject: [PATCH 01/73] fix: update fdroid/AndroidManifest.xml --- fdroid/src/main/AndroidManifest.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fdroid/src/main/AndroidManifest.xml b/fdroid/src/main/AndroidManifest.xml index c792adb89..9edc7a57f 100644 --- a/fdroid/src/main/AndroidManifest.xml +++ b/fdroid/src/main/AndroidManifest.xml @@ -20,6 +20,10 @@ android:hasFragileUserData="false" tools:ignore="HardcodedDebugMode"> + + \ No newline at end of file From 964568fbd7521df49558b8b65925440fba4b5785 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Sun, 17 Dec 2023 18:39:14 +0100 Subject: [PATCH 02/73] chore: update app version and build number --- core/build.gradle | 4 ++-- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 4 ++-- store/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index a151e5925..1d4207dcd 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,8 +30,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 128 - versionName "2.10.5" + versionCode 129 + versionName "2.10.6" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 385ec3563..4f585e1a6 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 128 - versionName "2.10.5" + versionCode 129 + versionName "2.10.6" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 0491ab7d8..5c60ef05e 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 128 - versionName "2.10.5" + versionCode 129 + versionName "2.10.6" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/site/build.gradle b/site/build.gradle index 7a0a722b5..46c6119b7 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 128 - versionName "2.10.5" + versionCode 129 + versionName "2.10.6" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/store/build.gradle b/store/build.gradle index bd962ccf9..c81b62dca 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,8 +32,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 128 - versionName "2.10.5" + versionCode 129 + versionName "2.10.6" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] From 1ffa005ea19c3097cbffb09f871aa1705f5d77bb Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 18 Dec 2023 09:24:40 +0100 Subject: [PATCH 03/73] docs: update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7218888..d370bebc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## Version 2.10.6 - 2023-12-18 + +[FIXED] Crash when opening the app on F-Droid + ## Version 2.10.5 - 2023-12-13 [IMPROVED] Show non-launchable and system apps in the Split Tunneling list From 84969609660d870a8475f4a3f83e9cd69019a25d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 00:12:52 +0000 Subject: [PATCH 04/73] build(deps): bump golang.org/x/crypto in /core/tools/libwg-go Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.7.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.7.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] --- core/tools/libwg-go/go.mod | 6 +++--- core/tools/libwg-go/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/tools/libwg-go/go.mod b/core/tools/libwg-go/go.mod index 0be5f7ef6..3a311a198 100644 --- a/core/tools/libwg-go/go.mod +++ b/core/tools/libwg-go/go.mod @@ -3,12 +3,12 @@ module golang.zx2c4.com/wireguard/android go 1.19 require ( - golang.org/x/sys v0.6.0 + golang.org/x/sys v0.15.0 golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 ) require ( - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.10.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect ) diff --git a/core/tools/libwg-go/go.sum b/core/tools/libwg-go/go.sum index 3b49b497d..6c99c891f 100644 --- a/core/tools/libwg-go/go.sum +++ b/core/tools/libwg-go/go.sum @@ -1,9 +1,9 @@ -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU= From abd48cfd00bfbccb9014e09e5451a086baf77d69 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 11 Jan 2024 17:19:24 +0100 Subject: [PATCH 05/73] feat(account): update SessionNewResponse.java --- .../ivpn/core/rest/data/session/SessionNewResponse.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java index cb469aee6..c9906bfbb 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java @@ -41,6 +41,9 @@ public class SessionNewResponse { @SerializedName("vpn_password") @Expose private String vpnPassword; + @SerializedName("device_name") + @Expose + private String deviceName; @SerializedName("service_status") @Expose private ServiceStatus serviceStatus; @@ -76,6 +79,10 @@ public String getVpnPassword() { return vpnPassword; } + public String getDeviceName() { + return deviceName; + } + public void setVpnPassword(String vpnPassword) { this.vpnPassword = vpnPassword; } From a1816aab88ac363f22b20145711d6cbeb463f21b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 11 Jan 2024 18:02:08 +0100 Subject: [PATCH 06/73] feat(account): update SessionStatusResponse.java --- .../ivpn/core/rest/data/session/SessionStatusResponse.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java b/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java index a4f387dbd..1120d5b74 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java @@ -31,6 +31,9 @@ public class SessionStatusResponse { @SerializedName("status") @Expose private Integer status; + @SerializedName("device_name") + @Expose + private String deviceName; @SerializedName("service_status") @Expose private ServiceStatus serviceStatus; @@ -43,6 +46,10 @@ public void setStatus(Integer status) { this.status = status; } + public String getDeviceName() { + return deviceName; + } + public ServiceStatus getServiceStatus() { return serviceStatus; } From aea543992a1161f214bdc3c15f74e95197e7480f Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 11 Jan 2024 18:03:20 +0100 Subject: [PATCH 07/73] feat(account): update ServiceStatus.java --- .../java/net/ivpn/core/rest/data/model/ServiceStatus.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java b/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java index 99c741d23..e04bf1770 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java +++ b/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java @@ -53,6 +53,9 @@ public class ServiceStatus { @SerializedName("capabilities") @Expose private List capabilities = null; + @SerializedName("device_management") + @Expose + private Boolean deviceManagement; public Boolean getIsActive() { return isActive; @@ -118,6 +121,10 @@ public void setCurrentPlan(String currentPlan) { this.currentPlan = currentPlan; } + public Boolean getDeviceManagement() { + return deviceManagement; + } + @Override public String toString() { return "ServiceStatus{" + From 94812168ff35800f8a98dc92ec7f133ae1a63620 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 12 Jan 2024 10:29:49 +0100 Subject: [PATCH 08/73] feat(account): update toString method --- .../main/java/net/ivpn/core/rest/data/model/ServiceStatus.java | 1 + .../java/net/ivpn/core/rest/data/session/SessionNewResponse.java | 1 + .../net/ivpn/core/rest/data/session/SessionStatusResponse.java | 1 + 3 files changed, 3 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java b/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java index e04bf1770..82aeae72a 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java +++ b/core/src/main/java/net/ivpn/core/rest/data/model/ServiceStatus.java @@ -135,6 +135,7 @@ public String toString() { ", isRenewable='" + isRenewable + '\'' + ", willAutoRebill='" + willAutoRebill + '\'' + ", isOnFreeTrial='" + isOnFreeTrial + '\'' + + ", deviceManagement='" + deviceManagement + '\'' + ", capabilities=" + capabilities + '}'; } diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java index c9906bfbb..445e8ee28 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewResponse.java @@ -108,6 +108,7 @@ public String toString() { return "SessionNewResponse{" + "status=" + status + ", serviceStatus=" + serviceStatus + + ", deviceName=" + deviceName + ", wireGuard=" + wireGuard + '}'; } diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java b/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java index 1120d5b74..8173b19a1 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionStatusResponse.java @@ -62,6 +62,7 @@ public void setServiceStatus(ServiceStatus serviceStatus) { public String toString() { return "SessionStatusResponse{" + "status=" + status + + ", deviceName=" + deviceName + ", serviceStatus=" + serviceStatus + '}'; } From cfa1e70e98fb452142df7927772ea957e4f10783 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 12 Jan 2024 11:22:12 +0100 Subject: [PATCH 09/73] feat(account): update SessionController.kt --- .../common/prefs/EncryptedUserPreference.kt | 22 +++++++++++++++++++ .../core/common/session/SessionController.kt | 3 +++ 2 files changed, 25 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/common/prefs/EncryptedUserPreference.kt b/core/src/main/java/net/ivpn/core/common/prefs/EncryptedUserPreference.kt index 6280262fc..837c72bc7 100644 --- a/core/src/main/java/net/ivpn/core/common/prefs/EncryptedUserPreference.kt +++ b/core/src/main/java/net/ivpn/core/common/prefs/EncryptedUserPreference.kt @@ -44,6 +44,8 @@ class EncryptedUserPreference @Inject constructor(val preference: Preference) { private const val SESSION_TOKEN = "SESSION_TOKEN" private const val SESSION_VPN_USERNAME = "SESSION_VPN_USERNAME" private const val SESSION_VPN_PASSWORD = "SESSION_VPN_PASSWORD" + private const val DEVICE_MANAGEMENT = "DEVICE_MANAGEMENT" + private const val DEVICE_NAME = "DEVICE_NAME" private const val BLANK_USERNAME = "BLANK_USERNAME" private const val BLANK_USERNAME_GENERATED_DATE = "BLANK_USERNAME_GENERATED_DATE" @@ -93,6 +95,18 @@ class EncryptedUserPreference @Inject constructor(val preference: Preference) { .apply() } + fun putDeviceManagement(deviceManagement: Boolean) { + sharedPreferences.edit() + .putBoolean(DEVICE_MANAGEMENT, deviceManagement) + .apply() + } + + fun putDeviceName(deviceName: String?) { + sharedPreferences.edit() + .putString(DEVICE_NAME, deviceName) + .apply() + } + fun putCapabilityMultiHop(isAvailable: Boolean) { sharedPreferences.edit() .putBoolean(USER_MULTI_HOP, isAvailable) @@ -139,6 +153,14 @@ class EncryptedUserPreference @Inject constructor(val preference: Preference) { return sharedPreferences.getString(SESSION_VPN_PASSWORD, "") } + fun getDeviceManagement(): Boolean { + return sharedPreferences.getBoolean(DEVICE_MANAGEMENT, false) + } + + fun getDeviceName(): String? { + return sharedPreferences.getString(DEVICE_NAME, "") + } + fun getSessionToken(): String { return sharedPreferences.getString(SESSION_TOKEN, "") ?: "" } diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index 12790b0a1..c01bfd026 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -146,6 +146,7 @@ class SessionController @Inject constructor( if (response.status != null && response.status == Responses.SUCCESS) { LOGGER.info("Session status response received successfully") LOGGER.info(response.toString()) + userPreference.putDeviceName(response.deviceName) saveSessionStatus(response.serviceStatus) onUpdateSuccess() } @@ -292,6 +293,7 @@ class SessionController @Inject constructor( userPreference.putSessionToken(response.token) userPreference.putSessionUsername(response.vpnUsername) userPreference.putSessionPassword(response.vpnPassword) + userPreference.putDeviceName(response.deviceName) saveSessionStatus(response.serviceStatus) } @@ -304,6 +306,7 @@ class SessionController @Inject constructor( userPreference.putCurrentPlan(serviceStatus.currentPlan) userPreference.putPaymentMethod(serviceStatus.paymentMethod) userPreference.putIsActive(serviceStatus.isActive) + userPreference.putDeviceManagement(serviceStatus.deviceManagement) if (serviceStatus.capabilities != null) { userPreference.putIsUserOnPrivateEmailBeta(serviceStatus.capabilities.contains(Responses.PRIVATE_EMAILS)) val multiHopCapabilities = serviceStatus.capabilities.contains(Responses.MULTI_HOP) From 5e10f588b732acf4211487b11e0f90f5e4c10285 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 12 Jan 2024 14:02:35 +0100 Subject: [PATCH 10/73] feat(account): update AccountViewModel.kt --- .../net/ivpn/core/v2/viewmodel/AccountViewModel.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index e5a7e28c5..affc436b1 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -58,6 +58,8 @@ class AccountViewModel @Inject constructor( val isNativeSubscription = ObservableBoolean() val availableUntil = ObservableLong() val isActive = ObservableBoolean() + val deviceManagement = ObservableBoolean() + val deviceName = ObservableField() val isExpired = ObservableBoolean() val isExpiredIn = ObservableBoolean() @@ -90,6 +92,8 @@ class AccountViewModel @Inject constructor( subscriptionPlan.set(getSubscriptionPlan()) isActive.set(getIsActiveValue()) paymentMethod = getPaymentMethodValue() + deviceManagement.set(getDeviceManagement()) + deviceName.set(getDeviceName()) updateExpireData() } @@ -260,6 +264,14 @@ class AccountViewModel @Inject constructor( return userPreference.getPaymentMethod() } + private fun getDeviceManagement(): Boolean { + return userPreference.getDeviceManagement() + } + + private fun getDeviceName(): String? { + return userPreference.getDeviceName() + } + interface AccountNavigator { fun onLogOut() From 45ccda7afa2bdae3c3f757239b1c1469dd06b9fe Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 12 Jan 2024 14:25:00 +0100 Subject: [PATCH 11/73] feat(account): update content_account.xml --- .../core/common/session/SessionController.kt | 4 ++- core/src/main/res/layout/content_account.xml | 27 +++++++++++++++++++ core/src/main/res/values/strings.xml | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index c01bfd026..df7183fe2 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -306,7 +306,9 @@ class SessionController @Inject constructor( userPreference.putCurrentPlan(serviceStatus.currentPlan) userPreference.putPaymentMethod(serviceStatus.paymentMethod) userPreference.putIsActive(serviceStatus.isActive) - userPreference.putDeviceManagement(serviceStatus.deviceManagement) + serviceStatus.deviceManagement?.let { + userPreference.putDeviceManagement(it) + } if (serviceStatus.capabilities != null) { userPreference.putIsUserOnPrivateEmailBeta(serviceStatus.capabilities.contains(Responses.PRIVATE_EMAILS)) val multiHopCapabilities = serviceStatus.capabilities.contains(Responses.MULTI_HOP) diff --git a/core/src/main/res/layout/content_account.xml b/core/src/main/res/layout/content_account.xml index 54632a020..c0d78891f 100644 --- a/core/src/main/res/layout/content_account.xml +++ b/core/src/main/res/layout/content_account.xml @@ -93,6 +93,33 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/username" /> + + + + Please save your account ID in a safe place, you will use it to connect on another IVPN App or log in to the client area of the IVPN website. You can find this account ID later in the IVPN App Account screen. Select your plan to continue Account ID copied + Device Name Your current location Connected to From c38979896f9d5b1ad27a143ea9adda66537459d8 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 12:19:05 +0100 Subject: [PATCH 12/73] feat(account): create SessionNewErrorResponse.kt --- .../rest/data/session/SessionNewErrorData.kt | 66 +++++++++++++++++++ .../data/session/SessionNewErrorResponse.kt | 54 +++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt create mode 100644 core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt new file mode 100644 index 000000000..54de33efa --- /dev/null +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt @@ -0,0 +1,66 @@ +package net.ivpn.core.rest.data.session; + +/* + IVPN Android app + https://github.com/ivpn/android-app + + Created by Juraj Hilje. + Copyright (c) 2024 IVPN Limited. + + This file is part of the IVPN Android app. + + The IVPN Android app is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) any later version. + + The IVPN Android app is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License + along with the IVPN Android app. If not, see . +*/ + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +class SessionNewErrorData { + + @SerializedName("current_plan") + @Expose + var currentPlan: String = "" + + @SerializedName("device_management") + @Expose + var deviceManagement: Boolean = false + + @SerializedName("device_management_url") + @Expose + var deviceManagementUrl: String = "" + + @SerializedName("limit") + @Expose + var limit: Int = 0 + + @SerializedName("payment_method") + @Expose + var paymentMethod: String = "" + + @SerializedName("upgradable") + @Expose + var upgradable: Boolean = false + + @SerializedName("upgrade_to_plan") + @Expose + var upgradeToPlan: String = "" + + @SerializedName("upgrade_to_url") + @Expose + var upgradeToUrl: String = "" + + override fun toString(): String { + return "SessionNewErrorData(currentPlan='$currentPlan', deviceManagement=$deviceManagement, deviceManagementUrl='$deviceManagementUrl', limit=$limit, paymentMethod='$paymentMethod', upgradable=$upgradable, upgradeToPlan='$upgradeToPlan', upgradeToUrl='$upgradeToUrl')" + } + +} diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt new file mode 100644 index 000000000..31ad0b247 --- /dev/null +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt @@ -0,0 +1,54 @@ +package net.ivpn.core.rest.data.session; + +/* + IVPN Android app + https://github.com/ivpn/android-app + + Created by Juraj Hilje. + Copyright (c) 2024 IVPN Limited. + + This file is part of the IVPN Android app. + + The IVPN Android app is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) any later version. + + The IVPN Android app is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License + along with the IVPN Android app. If not, see . +*/ + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +class SessionNewErrorResponse { + + @SerializedName("status") + @Expose + var status: Int = 0 + + @SerializedName("message") + @Expose + var message: String = "" + + @SerializedName("captcha_id") + @Expose + val captchaId: String? = null + + @SerializedName("captcha_image") + @Expose + val captchaImage: String? = null + + @SerializedName("data") + @Expose + var data:SessionNewErrorData? = null + + override fun toString(): String { + return "SessionNewErrorResponse(status=$status, message='$message', captchaId=$captchaId, captchaImage=$captchaImage, data=$data)" + } + +} From 92812ac4ebc5c310887a49418b480a304bb88b6b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 12:21:06 +0100 Subject: [PATCH 13/73] feat(account): update SessionController.kt --- .../src/main/java/net/ivpn/core/common/Mapper.kt | 12 ++++++++++++ .../core/common/session/SessionController.kt | 6 +++--- .../core/common/session/SessionListenerImpl.kt | 3 ++- .../net/ivpn/core/v2/login/LoginViewModel.kt | 16 +++++++--------- .../core/v2/viewmodel/ConnectionViewModel.kt | 3 ++- .../client/billing/BillingManagerWrapper.java | 3 ++- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/Mapper.kt b/core/src/main/java/net/ivpn/core/common/Mapper.kt index c309293f0..ca299c33e 100644 --- a/core/src/main/java/net/ivpn/core/common/Mapper.kt +++ b/core/src/main/java/net/ivpn/core/common/Mapper.kt @@ -29,6 +29,7 @@ import net.ivpn.core.rest.data.ServersListResponse import net.ivpn.core.rest.data.model.AntiTracker import net.ivpn.core.rest.data.model.Port import net.ivpn.core.rest.data.model.Server +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse import java.util.* @@ -105,4 +106,15 @@ object Mapper { null } } + + @JvmStatic + fun sessionNewErrorResponseFrom(json: String?): SessionNewErrorResponse? { + return if (json == null || json.isEmpty()) null else try { + Gson().fromJson(json, SessionNewErrorResponse::class.java) + } catch (jsonSyntaxException: JsonSyntaxException) { + null + } catch (jsonSyntaxException: IllegalStateException) { + null + } + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index df7183fe2..abec29b51 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -125,7 +125,7 @@ class SessionController @Inject constructor( override fun onError(error: String) { LOGGER.error("On create session error = $error") - val errorResponse = Mapper.errorResponseFrom(error) + val errorResponse = Mapper.sessionNewErrorResponseFrom(error) onCreateError(null, errorResponse) } }) @@ -235,7 +235,7 @@ class SessionController @Inject constructor( } } - private fun onCreateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + private fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { for (listener in listeners) { listener.onCreateError(throwable, errorResponse) } @@ -358,7 +358,7 @@ class SessionController @Inject constructor( fun onCreateSuccess(response: SessionNewResponse) - fun onCreateError(throwable: Throwable?, errorResponse: ErrorResponse?) + fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) fun onUpdateSuccess() diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt index fddd9aa5d..232199702 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt @@ -23,6 +23,7 @@ package net.ivpn.core.common.session */ import net.ivpn.core.common.session.SessionController.* +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse @@ -36,7 +37,7 @@ open class SessionListenerImpl: SessionListener { override fun onCreateSuccess(response: SessionNewResponse) { } - override fun onCreateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { } override fun onUpdateSuccess() { diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt index 4c63cda9a..8bce4e91b 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt @@ -35,8 +35,8 @@ import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.session.SessionListenerImpl import net.ivpn.core.common.utils.ConnectivityUtil import net.ivpn.core.rest.Responses +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse -import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.dialog.Dialogs import org.slf4j.LoggerFactory import java.io.InterruptedIOException @@ -127,7 +127,7 @@ class LoginViewModel @Inject constructor( this@LoginViewModel.onSuccess(response) } - override fun onCreateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { LOGGER.error("Login process: ERROR", throwable) if (!ConnectivityUtil.isOnline(context)) { navigator?.openErrorDialogue(Dialogs.CONNECTION_ERROR) @@ -268,12 +268,8 @@ class LoginViewModel @Inject constructor( } } - private fun handleErrorResponse(errorResponse: ErrorResponse?) { + private fun handleErrorResponse(errorResponse: SessionNewErrorResponse?) { errorResponse?.let { - if (it.status == null) { - navigator?.openErrorDialogue(Dialogs.SERVER_ERROR) - return - } } ?: kotlin.run { navigator?.openErrorDialogue(Dialogs.CREATE_SESSION_ERROR) return @@ -319,11 +315,13 @@ class LoginViewModel @Inject constructor( } Responses.WIREGUARD_KEY_INVALID, Responses.WIREGUARD_PUBLIC_KEY_EXIST, Responses.BAD_REQUEST, Responses.SESSION_SERVICE_ERROR -> { navigator?.openCustomErrorDialogue("${context.getString(R.string.dialogs_error)} ${errorResponse.status}", - if (errorResponse.message != null) errorResponse.message else "") + errorResponse.message + ) } else -> { navigator?.openCustomErrorDialogue("${context.getString(R.string.dialogs_error)} ${errorResponse.status}", - if (errorResponse.message != null) errorResponse.message else "") + errorResponse.message + ) } } } diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt index 7c4296bba..e57856497 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt @@ -35,6 +35,7 @@ import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.utils.ConnectivityUtil import net.ivpn.core.common.utils.StringUtil import net.ivpn.core.rest.Responses +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.connect.createSession.ConnectionNavigator @@ -257,7 +258,7 @@ class ConnectionViewModel @Inject constructor( } } - override fun onCreateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { if (!ConnectivityUtil.isOnline(context)) { navigator?.openErrorDialog(Dialogs.CONNECTION_ERROR) return diff --git a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java index 638913974..46e62dd5e 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java @@ -45,6 +45,7 @@ import net.ivpn.core.rest.data.addfunds.AddFundsResponse; import net.ivpn.core.rest.data.addfunds.InitialPaymentRequestBody; import net.ivpn.core.rest.data.addfunds.InitialPaymentResponse; +import net.ivpn.core.rest.data.session.SessionNewErrorResponse; import net.ivpn.core.rest.data.session.SessionNewResponse; import net.ivpn.core.rest.data.wireguard.ErrorResponse; import net.ivpn.core.rest.requests.common.Request; @@ -248,7 +249,7 @@ public void onCreateSuccess(@NotNull SessionNewResponse response) { } @Override - public void onCreateError(@Nullable Throwable throwable, @Nullable ErrorResponse errorResponse) { + public void onCreateError(@Nullable Throwable throwable, @Nullable SessionNewErrorResponse errorResponse) { LOGGER.info("On create session Error: " + throwable + "/n" + errorResponse); sessionController.unSubscribe(this); setPurchaseState(CREATE_SESSION_ERROR); From 338e2343cc802634aa0316dfe6d0586c03e34c65 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 14:27:44 +0100 Subject: [PATCH 14/73] feat(account): update CreateSessionFragment.java --- .../ivpn/core/v2/captcha/CaptchaFragment.kt | 3 +- .../createSession/CreateSessionFragment.java | 35 +++++++++++++++++-- .../net/ivpn/core/v2/login/LoginFragment.kt | 11 ++---- .../ivpn/core/v2/login/LoginNavigator.java | 3 +- .../net/ivpn/core/v2/login/LoginViewModel.kt | 2 +- .../java/net/ivpn/core/v2/tfa/TFAFragment.kt | 3 +- 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt index 465fc105e..bebd57cb7 100644 --- a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt @@ -39,6 +39,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.extension.setNavigationResultBoolean import net.ivpn.core.databinding.FragmentCaptchaBinding +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.login.LoginNavigator @@ -153,7 +154,7 @@ class CaptchaFragment : Fragment(), LoginNavigator { findNavController().popBackStack() } - override fun openSessionLimitReachedDialogue() { + override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index 5de15b891..ca2ac2564 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -39,14 +39,21 @@ import net.ivpn.core.R; import net.ivpn.core.databinding.BottomSheetBinding; +import net.ivpn.core.rest.data.session.SessionNewErrorResponse; import net.ivpn.core.v2.login.LoginFragment; +import net.ivpn.core.common.billing.addfunds.Plan; + +import java.util.Objects; public class CreateSessionFragment extends BottomSheetDialogFragment { private CreateSessionNavigator navigator; private BottomSheetBinding binding; - public CreateSessionFragment() { + private SessionNewErrorResponse error; + + public CreateSessionFragment(SessionNewErrorResponse error) { + this.error = error; } @Override @@ -65,9 +72,31 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - binding = DataBindingUtil.inflate( - inflater, R.layout.bottom_sheet, container, false); + Plan plan = Plan.Companion.getPlanByProductName(Objects.requireNonNull(error.getData()).getCurrentPlan()); + boolean deviceManagement = Objects.requireNonNull(error.getData()).getDeviceManagement(); + + // Device Management enabled, Pro plan + if (deviceManagement && plan.equals(Plan.PRO)) { + Log.d("INFO OK", "Device Management enabled, Pro plan"); + } + + // Device Management enabled, Pro plan + if (!deviceManagement && plan.equals(Plan.PRO)) { + Log.d("INFO OK", "Device Management disabled, Pro plan"); + } + + // Device Management enabled, Pro plan + if (deviceManagement && plan.equals(Plan.STANDARD)) { + Log.d("INFO OK", "Device Management enabled, Standard plan"); + } + + // Device Management enabled, Pro plan + if (!deviceManagement && plan.equals(Plan.STANDARD)) { + Log.d("INFO OK", "Device Management disabled, Standard plan"); + } + // Default + binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet, container, false); return binding.getRoot(); } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index 81f570c7d..c826fa748 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -44,6 +44,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.getNavigationResultBoolean import net.ivpn.core.common.extension.navigate import net.ivpn.core.databinding.FragmentLoginBinding +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.v2.connect.createSession.CreateSessionFragment import net.ivpn.core.v2.connect.createSession.CreateSessionNavigator import net.ivpn.core.v2.dialog.DialogBuilder @@ -153,12 +154,6 @@ class LoginFragment : Fragment(), LoginNavigator, binding.contentLayout.qrCode.setOnClickListener { openQRScanner() } - - getNavigationResultBoolean("session_limit_dialogue")?.observe(viewLifecycleOwner) { - if (it) { - openSessionLimitReachedDialogue() - } - } } private fun initToolbar() { @@ -195,12 +190,12 @@ class LoginFragment : Fragment(), LoginNavigator, DialogBuilder.createNotificationDialog(context, dialog) } - override fun openSessionLimitReachedDialogue() { + override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { if (!isAdded) { return } createSessionFragment = - CreateSessionFragment() + CreateSessionFragment(error) createSessionFragment?.let { it.show(childFragmentManager, it.tag) } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java b/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java index 08a8d4ae2..4c48edb7a 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java @@ -22,6 +22,7 @@ along with the IVPN Android app. If not, see . */ +import net.ivpn.core.rest.data.session.SessionNewErrorResponse; import net.ivpn.core.v2.dialog.Dialogs; public interface LoginNavigator { @@ -29,7 +30,7 @@ public interface LoginNavigator { void onLoginWithBlankAccount(); void onLoginWithInactiveAccount(); void onInvalidAccount(); - void openSessionLimitReachedDialogue(); + void openSessionLimitReachedDialogue(SessionNewErrorResponse error); void openCaptcha(); void openErrorDialogue(Dialogs dialogs); void openCustomErrorDialogue(String title, String message); diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt index 8bce4e91b..f1abaf76f 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt @@ -294,7 +294,7 @@ class LoginViewModel @Inject constructor( Responses.SESSION_TOO_MANY -> { pendingCaptcha = captcha.get() pending2FAToken = tfaToken.get() - navigator?.openSessionLimitReachedDialogue() + navigator?.openSessionLimitReachedDialogue(errorResponse) } Responses.INVALID_CAPTCHA -> { error.set("Invalid captcha, please try again") diff --git a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt index f2d19c091..d47817b19 100644 --- a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt @@ -38,6 +38,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.extension.setNavigationResultBoolean import net.ivpn.core.databinding.FragmentTfaBinding +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.v2.connect.createSession.CreateSessionFragment import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs @@ -163,7 +164,7 @@ class TFAFragment : Fragment(), LoginNavigator { //Nothing to do } - override fun openSessionLimitReachedDialogue() { + override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } From b99cf8c5d7c179b7020cc7591160d76338326eb9 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 14:32:44 +0100 Subject: [PATCH 15/73] feat(account): update ConnectionNavigator.java --- .../main/java/net/ivpn/core/v2/connect/ConnectFragment.kt | 5 +++-- .../core/v2/connect/createSession/ConnectionNavigator.java | 3 ++- .../java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index d8e417f86..7d11a358c 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -56,6 +56,7 @@ import net.ivpn.core.common.utils.ToastUtil import net.ivpn.core.databinding.FragmentConnectBinding import net.ivpn.core.rest.data.model.ServerLocation import net.ivpn.core.rest.data.model.ServerType +import net.ivpn.core.rest.data.session.SessionNewErrorResponse import net.ivpn.core.v2.MainActivity import net.ivpn.core.v2.connect.createSession.ConnectionNavigator import net.ivpn.core.v2.connect.createSession.ConnectionState @@ -802,9 +803,9 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, }) } - override fun openSessionLimitReachedDialogue() { + override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { createSessionFragment = - CreateSessionFragment() + CreateSessionFragment(error) createSessionFragment.show(childFragmentManager, createSessionFragment.tag) } diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java index a62077959..2289c5291 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java @@ -22,6 +22,7 @@ along with the IVPN Android app. If not, see . */ +import net.ivpn.core.rest.data.session.SessionNewErrorResponse; import net.ivpn.core.v2.dialog.Dialogs; public interface ConnectionNavigator { @@ -36,7 +37,7 @@ public interface ConnectionNavigator { void logout(); - void openSessionLimitReachedDialogue(); + void openSessionLimitReachedDialogue(SessionNewErrorResponse error); void accountVerificationFailed(); diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt index e57856497..b8289bdbb 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt @@ -277,7 +277,7 @@ class ConnectionViewModel @Inject constructor( navigator?.logout() } Responses.SESSION_TOO_MANY -> { - navigator?.openSessionLimitReachedDialogue() + navigator?.openSessionLimitReachedDialogue(errorResponse) } } } From 1ad208626a88dac50998eadd35a1d5f96c2c481c Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 17:04:57 +0100 Subject: [PATCH 16/73] feat(account): update CreateSessionFragment.java --- .../createSession/CreateSessionFragment.java | 131 +++++++++++-- .../createSession/CreateSessionNavigator.java | 4 + .../net/ivpn/core/v2/login/LoginFragment.kt | 8 + core/src/main/res/layout/bottom_sheet.xml | 8 +- .../main/res/layout/bottom_sheet_dm_pro.xml | 151 +++++++++++++++ .../res/layout/bottom_sheet_dm_standard.xml | 179 ++++++++++++++++++ core/src/main/res/layout/bottom_sheet_pro.xml | 123 ++++++++++++ .../main/res/layout/bottom_sheet_standard.xml | 151 +++++++++++++++ core/src/main/res/values/strings.xml | 7 + 9 files changed, 746 insertions(+), 16 deletions(-) create mode 100644 core/src/main/res/layout/bottom_sheet_dm_pro.xml create mode 100644 core/src/main/res/layout/bottom_sheet_dm_standard.xml create mode 100644 core/src/main/res/layout/bottom_sheet_pro.xml create mode 100644 core/src/main/res/layout/bottom_sheet_standard.xml diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index ca2ac2564..cea623a15 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -39,6 +39,10 @@ import net.ivpn.core.R; import net.ivpn.core.databinding.BottomSheetBinding; +import net.ivpn.core.databinding.BottomSheetDmProBinding; +import net.ivpn.core.databinding.BottomSheetProBinding; +import net.ivpn.core.databinding.BottomSheetDmStandardBinding; +import net.ivpn.core.databinding.BottomSheetStandardBinding; import net.ivpn.core.rest.data.session.SessionNewErrorResponse; import net.ivpn.core.v2.login.LoginFragment; import net.ivpn.core.common.billing.addfunds.Plan; @@ -48,9 +52,8 @@ public class CreateSessionFragment extends BottomSheetDialogFragment { private CreateSessionNavigator navigator; - private BottomSheetBinding binding; - private SessionNewErrorResponse error; + private final SessionNewErrorResponse error; public CreateSessionFragment(SessionNewErrorResponse error) { this.error = error; @@ -77,27 +80,26 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c // Device Management enabled, Pro plan if (deviceManagement && plan.equals(Plan.PRO)) { - Log.d("INFO OK", "Device Management enabled, Pro plan"); + return getDmProBinding(inflater, container); } - // Device Management enabled, Pro plan + // Device Management disabled, Pro plan if (!deviceManagement && plan.equals(Plan.PRO)) { - Log.d("INFO OK", "Device Management disabled, Pro plan"); + return getProBinding(inflater, container); } - // Device Management enabled, Pro plan + // Device Management enabled, Standard plan if (deviceManagement && plan.equals(Plan.STANDARD)) { - Log.d("INFO OK", "Device Management enabled, Standard plan"); + return getDmStandardBinding(inflater, container); } - // Device Management enabled, Pro plan + // Device Management disabled, Standard plan if (!deviceManagement && plan.equals(Plan.STANDARD)) { - Log.d("INFO OK", "Device Management disabled, Standard plan"); + return getStandardBinding(inflater, container); } // Default - binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet, container, false); - return binding.getRoot(); + return getDefaultBinding(inflater, container); } @Override @@ -117,7 +119,13 @@ public void show(FragmentManager manager, String tag) { } } - private void init() { + private View getDefaultBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet, container, false); + binding.forceLogout.setOnClickListener(view -> { + if (navigator != null) { + navigator.onForceLogout(); + } + }); binding.tryAgain.setOnClickListener(view -> { if (navigator != null) { navigator.tryAgain(); @@ -128,10 +136,109 @@ private void init() { navigator.cancel(); } }); + return binding.getRoot(); + } + + private View getDmProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetDmProBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_dm_pro, container, false); binding.forceLogout.setOnClickListener(view -> { if (navigator != null) { navigator.onForceLogout(); } }); + binding.enableDeviceManagement.setOnClickListener(view -> { + if (navigator != null) { + navigator.enableDeviceManagement(); + } + }); + binding.tryAgain.setOnClickListener(view -> { + if (navigator != null) { + navigator.tryAgain(); + } + }); + binding.close.setOnClickListener(view -> { + if (navigator != null) { + navigator.cancel(); + } + }); + return binding.getRoot(); + } + + private View getProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetProBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_pro, container, false); + binding.forceLogout.setOnClickListener(view -> { + if (navigator != null) { + navigator.onForceLogout(); + } + }); + binding.enableDeviceManagement.setOnClickListener(view -> { + if (navigator != null) { + navigator.enableDeviceManagement(); + } + }); + binding.close.setOnClickListener(view -> { + if (navigator != null) { + navigator.cancel(); + } + }); + return binding.getRoot(); + } + + private View getDmStandardBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetDmStandardBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_dm_standard, container, false); + binding.forceLogout.setOnClickListener(view -> { + if (navigator != null) { + navigator.onForceLogout(); + } + }); + binding.enableDeviceManagement.setOnClickListener(view -> { + if (navigator != null) { + navigator.enableDeviceManagement(); + } + }); + binding.tryAgain.setOnClickListener(view -> { + if (navigator != null) { + navigator.tryAgain(); + } + }); + binding.upgradePlan.setOnClickListener(view -> { + if (navigator != null) { + navigator.upgradePlan(); + } + }); + binding.close.setOnClickListener(view -> { + if (navigator != null) { + navigator.cancel(); + } + }); + return binding.getRoot(); + } + + private View getStandardBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetStandardBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_standard, container, false); + binding.forceLogout.setOnClickListener(view -> { + if (navigator != null) { + navigator.onForceLogout(); + } + }); + binding.enableDeviceManagement.setOnClickListener(view -> { + if (navigator != null) { + navigator.enableDeviceManagement(); + } + }); + binding.upgradePlan.setOnClickListener(view -> { + if (navigator != null) { + navigator.upgradePlan(); + } + }); + binding.close.setOnClickListener(view -> { + if (navigator != null) { + navigator.cancel(); + } + }); + return binding.getRoot(); + } + + private void init() { } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java index 5ecec7736..c5a1fdce4 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java @@ -28,5 +28,9 @@ public interface CreateSessionNavigator { void tryAgain(); + void enableDeviceManagement(); + + void upgradePlan(); + void cancel(); } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index c826fa748..a5896b533 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -240,6 +240,14 @@ class LoginFragment : Fragment(), LoginNavigator, createSessionFragment?.dismissAllowingStateLoss() } + override fun enableDeviceManagement() { + TODO("Not yet implemented") + } + + override fun upgradePlan() { + TODO("Not yet implemented") + } + override fun cancel() { createSessionFragment?.dismissAllowingStateLoss() } diff --git a/core/src/main/res/layout/bottom_sheet.xml b/core/src/main/res/layout/bottom_sheet.xml index 3796e080b..a207d5255 100644 --- a/core/src/main/res/layout/bottom_sheet.xml +++ b/core/src/main/res/layout/bottom_sheet.xml @@ -27,7 +27,7 @@ android:layout_marginBottom="20dp" android:fontFamily="sans-serif" android:lineSpacingExtra="8sp" - android:text="You have exceeded the maximum number of sessions" + android:text="@string/dialogs_session_too_many_message_short" android:textColor="@color/bottom_sheet_text" android:alpha="0.8" android:textSize="16sp" @@ -56,7 +56,7 @@ android:layout_height="wrap_content" android:layout_marginStart="24dp" android:fontFamily="sans-serif" - android:text="Log out of all other devices" + android:text="@string/dialogs_session_log_out_all" android:textColor="@color/bottom_sheet_text" android:textSize="16sp" android:textStyle="normal" /> @@ -84,7 +84,7 @@ android:layout_height="wrap_content" android:layout_marginStart="24dp" android:fontFamily="sans-serif" - android:text="Try again" + android:text="@string/dialogs_session_retry" android:textColor="@color/bottom_sheet_text" android:textSize="16sp" android:textStyle="normal" /> @@ -112,7 +112,7 @@ android:layout_height="wrap_content" android:layout_marginStart="24dp" android:fontFamily="sans-serif" - android:text="Close" + android:text="@string/dialogs_session_cancel" android:textColor="@color/bottom_sheet_text" android:textSize="16sp" android:textStyle="normal" /> diff --git a/core/src/main/res/layout/bottom_sheet_dm_pro.xml b/core/src/main/res/layout/bottom_sheet_dm_pro.xml new file mode 100644 index 000000000..61962ab3b --- /dev/null +++ b/core/src/main/res/layout/bottom_sheet_dm_pro.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/res/layout/bottom_sheet_dm_standard.xml b/core/src/main/res/layout/bottom_sheet_dm_standard.xml new file mode 100644 index 000000000..1e708cbe8 --- /dev/null +++ b/core/src/main/res/layout/bottom_sheet_dm_standard.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/res/layout/bottom_sheet_pro.xml b/core/src/main/res/layout/bottom_sheet_pro.xml new file mode 100644 index 000000000..f03a16c75 --- /dev/null +++ b/core/src/main/res/layout/bottom_sheet_pro.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/res/layout/bottom_sheet_standard.xml b/core/src/main/res/layout/bottom_sheet_standard.xml new file mode 100644 index 000000000..d587bb718 --- /dev/null +++ b/core/src/main/res/layout/bottom_sheet_standard.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 2ac855bc1..59a5cb18e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -350,7 +350,14 @@ Session limit You\'ve reached the session limit, force login to logout of all other devices. + You have exceeded the maximum number of sessions Force login + Log out from all devices + Retry + Visit Device Management + Enable Device Management + Upgrade for 7 devices + Cancel login Error The format of your email address is not correct, please check and try again. From c9fd5c0cfaa1903c350790bc8bf7bffad9c2338f Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 18:33:46 +0100 Subject: [PATCH 17/73] feat(account): update LoginFragment.kt --- .../main/java/net/ivpn/core/v2/login/LoginFragment.kt | 9 +++++++-- core/src/main/res/layout/bottom_sheet.xml | 2 +- core/src/main/res/layout/bottom_sheet_dm_pro.xml | 2 +- core/src/main/res/layout/bottom_sheet_dm_standard.xml | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index a5896b533..f9a5e6d9e 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -24,6 +24,7 @@ package net.ivpn.core.v2.login import android.content.Context import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.* import android.view.inputmethod.EditorInfo @@ -241,11 +242,15 @@ class LoginFragment : Fragment(), LoginNavigator, } override fun enableDeviceManagement() { - TODO("Not yet implemented") + val openURL = Intent(Intent.ACTION_VIEW) + openURL.data = Uri.parse("https://www.ivpn.net/account/device-management") + startActivity(openURL) } override fun upgradePlan() { - TODO("Not yet implemented") + val openURL = Intent(Intent.ACTION_VIEW) + openURL.data = Uri.parse("https://www.ivpn.net/account/change-product") + startActivity(openURL) } override fun cancel() { diff --git a/core/src/main/res/layout/bottom_sheet.xml b/core/src/main/res/layout/bottom_sheet.xml index a207d5255..3ff6139ee 100644 --- a/core/src/main/res/layout/bottom_sheet.xml +++ b/core/src/main/res/layout/bottom_sheet.xml @@ -75,7 +75,7 @@ diff --git a/core/src/main/res/layout/bottom_sheet_dm_pro.xml b/core/src/main/res/layout/bottom_sheet_dm_pro.xml index 61962ab3b..5c949748d 100644 --- a/core/src/main/res/layout/bottom_sheet_dm_pro.xml +++ b/core/src/main/res/layout/bottom_sheet_dm_pro.xml @@ -103,7 +103,7 @@ diff --git a/core/src/main/res/layout/bottom_sheet_dm_standard.xml b/core/src/main/res/layout/bottom_sheet_dm_standard.xml index 1e708cbe8..f53f643a9 100644 --- a/core/src/main/res/layout/bottom_sheet_dm_standard.xml +++ b/core/src/main/res/layout/bottom_sheet_dm_standard.xml @@ -103,7 +103,7 @@ From 5488a0863b32da72894f59ffba6cbd79158e82dd Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jan 2024 19:57:32 +0100 Subject: [PATCH 18/73] feat(account): update CreateSessionNavigator.java --- .../createSession/CreateSessionFragment.java | 18 ++++++++++++------ .../createSession/CreateSessionNavigator.java | 4 ++-- .../net/ivpn/core/v2/login/LoginFragment.kt | 8 ++++---- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index cea623a15..c538847b6 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -141,6 +141,7 @@ private View getDefaultBinding(@NonNull LayoutInflater inflater, @Nullable ViewG private View getDmProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { BottomSheetDmProBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_dm_pro, container, false); + String deviceManagementUrl = Objects.requireNonNull(error.getData()).getDeviceManagementUrl(); binding.forceLogout.setOnClickListener(view -> { if (navigator != null) { navigator.onForceLogout(); @@ -148,7 +149,7 @@ private View getDmProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGro }); binding.enableDeviceManagement.setOnClickListener(view -> { if (navigator != null) { - navigator.enableDeviceManagement(); + navigator.enableDeviceManagement(deviceManagementUrl); } }); binding.tryAgain.setOnClickListener(view -> { @@ -166,6 +167,7 @@ private View getDmProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGro private View getProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { BottomSheetProBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_pro, container, false); + String deviceManagementUrl = Objects.requireNonNull(error.getData()).getDeviceManagementUrl(); binding.forceLogout.setOnClickListener(view -> { if (navigator != null) { navigator.onForceLogout(); @@ -173,7 +175,7 @@ private View getProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup }); binding.enableDeviceManagement.setOnClickListener(view -> { if (navigator != null) { - navigator.enableDeviceManagement(); + navigator.enableDeviceManagement(deviceManagementUrl); } }); binding.close.setOnClickListener(view -> { @@ -186,6 +188,8 @@ private View getProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup private View getDmStandardBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { BottomSheetDmStandardBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_dm_standard, container, false); + String deviceManagementUrl = Objects.requireNonNull(error.getData()).getDeviceManagementUrl(); + String upgradeToUrl = Objects.requireNonNull(error.getData()).getUpgradeToUrl(); binding.forceLogout.setOnClickListener(view -> { if (navigator != null) { navigator.onForceLogout(); @@ -193,7 +197,7 @@ private View getDmStandardBinding(@NonNull LayoutInflater inflater, @Nullable Vi }); binding.enableDeviceManagement.setOnClickListener(view -> { if (navigator != null) { - navigator.enableDeviceManagement(); + navigator.enableDeviceManagement(deviceManagementUrl); } }); binding.tryAgain.setOnClickListener(view -> { @@ -203,7 +207,7 @@ private View getDmStandardBinding(@NonNull LayoutInflater inflater, @Nullable Vi }); binding.upgradePlan.setOnClickListener(view -> { if (navigator != null) { - navigator.upgradePlan(); + navigator.upgradePlan(upgradeToUrl); } }); binding.close.setOnClickListener(view -> { @@ -216,6 +220,8 @@ private View getDmStandardBinding(@NonNull LayoutInflater inflater, @Nullable Vi private View getStandardBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { BottomSheetStandardBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_standard, container, false); + String deviceManagementUrl = Objects.requireNonNull(error.getData()).getDeviceManagementUrl(); + String upgradeToUrl = Objects.requireNonNull(error.getData()).getUpgradeToUrl(); binding.forceLogout.setOnClickListener(view -> { if (navigator != null) { navigator.onForceLogout(); @@ -223,12 +229,12 @@ private View getStandardBinding(@NonNull LayoutInflater inflater, @Nullable View }); binding.enableDeviceManagement.setOnClickListener(view -> { if (navigator != null) { - navigator.enableDeviceManagement(); + navigator.enableDeviceManagement(deviceManagementUrl); } }); binding.upgradePlan.setOnClickListener(view -> { if (navigator != null) { - navigator.upgradePlan(); + navigator.upgradePlan(upgradeToUrl); } }); binding.close.setOnClickListener(view -> { diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java index c5a1fdce4..392822bb4 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionNavigator.java @@ -28,9 +28,9 @@ public interface CreateSessionNavigator { void tryAgain(); - void enableDeviceManagement(); + void enableDeviceManagement(String url); - void upgradePlan(); + void upgradePlan(String url); void cancel(); } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index f9a5e6d9e..319cc807c 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -241,15 +241,15 @@ class LoginFragment : Fragment(), LoginNavigator, createSessionFragment?.dismissAllowingStateLoss() } - override fun enableDeviceManagement() { + override fun enableDeviceManagement(url: String) { val openURL = Intent(Intent.ACTION_VIEW) - openURL.data = Uri.parse("https://www.ivpn.net/account/device-management") + openURL.data = Uri.parse(url) startActivity(openURL) } - override fun upgradePlan() { + override fun upgradePlan(url: String) { val openURL = Intent(Intent.ACTION_VIEW) - openURL.data = Uri.parse("https://www.ivpn.net/account/change-product") + openURL.data = Uri.parse(url) startActivity(openURL) } From 60099a5db53fbf7cada31d5c6d061d99c9c17b61 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 18 Jan 2024 11:18:35 +0100 Subject: [PATCH 19/73] feat(account): update bottom_sheet.xml --- core/src/main/res/layout/bottom_sheet_pro.xml | 28 +++++++++++++++++++ .../main/res/layout/bottom_sheet_standard.xml | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/core/src/main/res/layout/bottom_sheet_pro.xml b/core/src/main/res/layout/bottom_sheet_pro.xml index f03a16c75..0b303ca04 100644 --- a/core/src/main/res/layout/bottom_sheet_pro.xml +++ b/core/src/main/res/layout/bottom_sheet_pro.xml @@ -91,6 +91,34 @@ + + + + + + + + + + + + + + + + Date: Thu, 18 Jan 2024 11:23:01 +0100 Subject: [PATCH 20/73] feat(account): update CreateSessionFragment.java --- .../createSession/CreateSessionFragment.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index c538847b6..e7d965684 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -77,24 +77,25 @@ public void onCreate(@Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Plan plan = Plan.Companion.getPlanByProductName(Objects.requireNonNull(error.getData()).getCurrentPlan()); boolean deviceManagement = Objects.requireNonNull(error.getData()).getDeviceManagement(); + boolean isAccountNewStyle = Objects.requireNonNull(error.getData()).getPaymentMethod().equals("prepaid"); // Device Management enabled, Pro plan - if (deviceManagement && plan.equals(Plan.PRO)) { + if (deviceManagement && plan.equals(Plan.PRO) && isAccountNewStyle) { return getDmProBinding(inflater, container); } // Device Management disabled, Pro plan - if (!deviceManagement && plan.equals(Plan.PRO)) { + if (!deviceManagement && plan.equals(Plan.PRO) && isAccountNewStyle) { return getProBinding(inflater, container); } // Device Management enabled, Standard plan - if (deviceManagement && plan.equals(Plan.STANDARD)) { + if (deviceManagement && plan.equals(Plan.STANDARD) && isAccountNewStyle) { return getDmStandardBinding(inflater, container); } // Device Management disabled, Standard plan - if (!deviceManagement && plan.equals(Plan.STANDARD)) { + if (!deviceManagement && plan.equals(Plan.STANDARD) && isAccountNewStyle) { return getStandardBinding(inflater, container); } @@ -178,6 +179,11 @@ private View getProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup navigator.enableDeviceManagement(deviceManagementUrl); } }); + binding.tryAgain.setOnClickListener(view -> { + if (navigator != null) { + navigator.tryAgain(); + } + }); binding.close.setOnClickListener(view -> { if (navigator != null) { navigator.cancel(); @@ -232,6 +238,11 @@ private View getStandardBinding(@NonNull LayoutInflater inflater, @Nullable View navigator.enableDeviceManagement(deviceManagementUrl); } }); + binding.tryAgain.setOnClickListener(view -> { + if (navigator != null) { + navigator.tryAgain(); + } + }); binding.upgradePlan.setOnClickListener(view -> { if (navigator != null) { navigator.upgradePlan(upgradeToUrl); From 1ce651e4ea564ce709589782d4a32192a0d85ef0 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 19 Jan 2024 10:02:26 +0100 Subject: [PATCH 21/73] feat(account): update SessionController.kt --- .../ivpn/core/common/session/SessionController.kt | 9 +++++++++ .../ivpn/core/common/session/SessionListenerImpl.kt | 3 +++ .../net/ivpn/core/v2/account/AccountFragment.kt | 5 +++-- .../net/ivpn/core/v2/connect/ConnectFragment.kt | 13 ++++++++++++- .../net/ivpn/core/v2/viewmodel/AccountViewModel.kt | 6 ++++++ .../ivpn/core/v2/viewmodel/ConnectionViewModel.kt | 3 +++ 6 files changed, 36 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index abec29b51..bda96351e 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -167,6 +167,7 @@ class SessionController @Inject constructor( if ((it.status == Responses.SESSION_NOT_FOUND)) { clearSessionData() onRemoveSuccess() + onDeviceLoggedOut() } } onUpdateError(null, errorResponse) @@ -253,6 +254,12 @@ class SessionController @Inject constructor( } } + private fun onDeviceLoggedOut() { + for (listener in listeners) { + listener.onDeviceLoggedOut() + } + } + fun clearData() { IVPNApplication.appComponent.provideComponentUtil().resetComponents() ViewModelCleaner().fullClean() @@ -363,5 +370,7 @@ class SessionController @Inject constructor( fun onUpdateSuccess() fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) + + fun onDeviceLoggedOut() } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt index 232199702..cee57a79e 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt @@ -45,4 +45,7 @@ open class SessionListenerImpl: SessionListener { override fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { } + + override fun onDeviceLoggedOut() { + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt index 0a552416f..e7e8c686a 100644 --- a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt @@ -44,8 +44,6 @@ import net.ivpn.core.databinding.FragmentAccountBinding import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.MainActivity -import net.ivpn.core.v2.connect.ConnectFragmentDirections -import net.ivpn.core.v2.connect.createSession.CreateSessionFragment import net.ivpn.core.v2.signup.SignUpController import net.ivpn.core.v2.viewmodel.AccountViewModel import org.slf4j.LoggerFactory @@ -174,4 +172,7 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { account.forceLogout() } } + + override fun onDeviceLoggedOut() { + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 7d11a358c..90aba66d6 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -74,7 +74,7 @@ import javax.inject.Inject class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, ConnectionNavigator, MapDialogs.GatewayListener, MapDialogs.LocationListener, - LocationViewModel.LocationUpdatesUIListener { + LocationViewModel.LocationUpdatesUIListener, AccountViewModel.AccountNavigator { companion object { private val LOGGER = LoggerFactory.getLogger(ConnectFragment::class.java) @@ -240,6 +240,7 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, multihop.navigator = this connect.navigator = this location.uiListener = this + account.navigator = this binding.location = location binding.connection = connect @@ -845,4 +846,14 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, override fun onLocationUpdated() { recalculatePeekHeight() } + + override fun onLogOut() { + } + + override fun onLogOutFailed() { + } + + override fun onDeviceLoggedOut() { + openLoginScreen() + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index affc436b1..a33e00457 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -79,6 +79,10 @@ class AccountViewModel @Inject constructor( override fun onRemoveError() { onRemoveSessionFailed() } + + override fun onDeviceLoggedOut() { + navigator?.onDeviceLoggedOut() + } }) } @@ -276,6 +280,8 @@ class AccountViewModel @Inject constructor( fun onLogOut() fun onLogOutFailed() + + fun onDeviceLoggedOut() } enum class Type { diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt index b8289bdbb..3fa0bb941 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt @@ -292,4 +292,7 @@ class ConnectionViewModel @Inject constructor( } } } + + override fun onDeviceLoggedOut() { + } } \ No newline at end of file From f52a3390669f7142e2565add58f534061842a6e4 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 19 Jan 2024 12:29:59 +0100 Subject: [PATCH 22/73] feat(account): add logged out dialog in LoginFragment.kt --- .../net/ivpn/core/v2/connect/ConnectFragment.kt | 6 +++--- .../java/net/ivpn/core/v2/dialog/Dialogs.java | 3 ++- .../java/net/ivpn/core/v2/login/LoginFragment.kt | 15 ++++++++++----- core/src/main/res/navigation/nav_graph.xml | 4 ++++ core/src/main/res/values/strings.xml | 3 +++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 90aba66d6..a558a816c 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -703,8 +703,8 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, navigate(action) } - private fun openLoginScreen() { - val action = ConnectFragmentDirections.actionConnectFragmentToLoginFragment() + private fun openLoginScreen(showLogoutAlert: Boolean = false) { + val action = ConnectFragmentDirections.actionConnectFragmentToLoginFragment(showLogoutAlert) navigate(action) } @@ -854,6 +854,6 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, } override fun onDeviceLoggedOut() { - openLoginScreen() + openLoginScreen(true) } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/dialog/Dialogs.java b/core/src/main/java/net/ivpn/core/v2/dialog/Dialogs.java index 4c20c69eb..93ccd3e9b 100644 --- a/core/src/main/java/net/ivpn/core/v2/dialog/Dialogs.java +++ b/core/src/main/java/net/ivpn/core/v2/dialog/Dialogs.java @@ -79,7 +79,8 @@ public enum Dialogs { MOCK_LOCATION_APP_ERROR(R.string.dialogs_mock_wrong_app, R.string.dialogs_mock_wrong_app_message, -1, R.string.dialogs_ok), REMOVE_KILL_SWITCH(R.string.dialogs_please_note, R.string.dialogs_remove_kill_switch, R.string.dialogs_to_read_more, R.string.dialogs_ok), WG_CANT_CHANGE_PORT(R.string.dialogs_please_note, R.string.dialogs_wireguard_impossible_change_port, -1, R.string.dialogs_ok), - WG_QUANTUM_RESISTANCE_INFO(R.string.protocol_wg_quantum_resistance, R.string.protocol_wg_quantum_resistance_info, -1, R.string.dialogs_ok); + WG_QUANTUM_RESISTANCE_INFO(R.string.protocol_wg_quantum_resistance, R.string.protocol_wg_quantum_resistance_info, -1, R.string.dialogs_ok), + DEVICE_LOGGED_OUT(R.string.dialogs_device_logged_out_title, R.string.dialogs_device_logged_out_message, -1, R.string.dialogs_ok); private int titleId; private int messageId; diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index 319cc807c..100f1d2a4 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -32,17 +32,15 @@ import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupWithNavController import com.google.zxing.integration.android.IntentIntegrator import com.google.zxing.integration.android.IntentResult -//import com.google.zxing.integration.android.IntentIntegrator -//import com.google.zxing.integration.android.IntentResult import net.ivpn.core.IVPNApplication import net.ivpn.core.R import net.ivpn.core.common.billing.addfunds.Plan import net.ivpn.core.common.extension.findNavControllerSafely -import net.ivpn.core.common.extension.getNavigationResultBoolean import net.ivpn.core.common.extension.navigate import net.ivpn.core.databinding.FragmentLoginBinding import net.ivpn.core.rest.data.session.SessionNewErrorResponse @@ -54,10 +52,8 @@ import net.ivpn.core.v2.MainActivity import net.ivpn.core.v2.qr.QRActivity import net.ivpn.core.v2.signup.CreateAccountNavigator import net.ivpn.core.v2.signup.SignUpController -//import net.ivpn.client.v2.qr.QRActivity import org.slf4j.LoggerFactory import javax.inject.Inject -import kotlin.math.sign class LoginFragment : Fragment(), LoginNavigator, CreateSessionNavigator, CreateAccountNavigator { @@ -77,6 +73,8 @@ class LoginFragment : Fragment(), LoginNavigator, private var originalMode: Int? = null + private val args : LoginFragmentArgs by navArgs() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -118,6 +116,7 @@ class LoginFragment : Fragment(), LoginNavigator, IVPNApplication.appComponent.provideActivityComponent().create().inject(this) initViews() initToolbar() + parseNavArgs() } @Deprecated("Deprecated in Java") @@ -174,6 +173,12 @@ class LoginFragment : Fragment(), LoginNavigator, } } + private fun parseNavArgs() { + if (args.showLogoutAlert) { + DialogBuilder.createNotificationDialog(context, Dialogs.DEVICE_LOGGED_OUT); + } + } + private fun createBlankAccount() { signUp.signUp(findNavControllerSafely()) } diff --git a/core/src/main/res/navigation/nav_graph.xml b/core/src/main/res/navigation/nav_graph.xml index 2ef64f083..4939c11df 100644 --- a/core/src/main/res/navigation/nav_graph.xml +++ b/core/src/main/res/navigation/nav_graph.xml @@ -131,6 +131,10 @@ android:id="@+id/loginFragment" android:name="net.ivpn.core.v2.login.LoginFragment" android:label="Log in"> + It is not possible to use the preferred port setting when Multi-Hop is enabled. + You are logged out + You have been redirected to the login page to re-enter your credentials. + Are you sure? This will disconnect you from IVPN. Log out and clear app settings Log out From cc0fa2882d480a62b42256fd95f1c7b1fc7ef78c Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 19 Jan 2024 14:07:41 +0100 Subject: [PATCH 23/73] feat(account): update strings.xml --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7e4dbebf6..329196ebe 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -356,7 +356,7 @@ Retry Visit Device Management Enable Device Management - Upgrade for 7 devices + Switch to IVPN Pro Cancel login Error From 689095ba6c77edb7246ef7c21e00517484512e15 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jan 2024 10:06:16 +0100 Subject: [PATCH 24/73] feat(account): update CreateSessionFragment.java --- .../createSession/CreateSessionFragment.java | 34 +++- .../layout/bottom_sheet_legacy_standard.xml | 151 ++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 core/src/main/res/layout/bottom_sheet_legacy_standard.xml diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index e7d965684..80c8ef69b 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -40,6 +40,7 @@ import net.ivpn.core.R; import net.ivpn.core.databinding.BottomSheetBinding; import net.ivpn.core.databinding.BottomSheetDmProBinding; +import net.ivpn.core.databinding.BottomSheetLegacyStandardBinding; import net.ivpn.core.databinding.BottomSheetProBinding; import net.ivpn.core.databinding.BottomSheetDmStandardBinding; import net.ivpn.core.databinding.BottomSheetStandardBinding; @@ -99,7 +100,12 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c return getStandardBinding(inflater, container); } - // Default + // Legacy account, Standard plan + if (plan.equals(Plan.STANDARD)) { + return getLegacyStandardBinding(inflater, container); + } + + // Legacy account, Pro plan return getDefaultBinding(inflater, container); } @@ -140,6 +146,32 @@ private View getDefaultBinding(@NonNull LayoutInflater inflater, @Nullable ViewG return binding.getRoot(); } + private View getLegacyStandardBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { + BottomSheetLegacyStandardBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_legacy_standard, container, false); + String upgradeToUrl = Objects.requireNonNull(error.getData()).getUpgradeToUrl(); + binding.forceLogout.setOnClickListener(view -> { + if (navigator != null) { + navigator.onForceLogout(); + } + }); + binding.tryAgain.setOnClickListener(view -> { + if (navigator != null) { + navigator.tryAgain(); + } + }); + binding.upgradePlan.setOnClickListener(view -> { + if (navigator != null) { + navigator.upgradePlan(upgradeToUrl); + } + }); + binding.close.setOnClickListener(view -> { + if (navigator != null) { + navigator.cancel(); + } + }); + return binding.getRoot(); + } + private View getDmProBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) { BottomSheetDmProBinding binding = DataBindingUtil.inflate(inflater, R.layout.bottom_sheet_dm_pro, container, false); String deviceManagementUrl = Objects.requireNonNull(error.getData()).getDeviceManagementUrl(); diff --git a/core/src/main/res/layout/bottom_sheet_legacy_standard.xml b/core/src/main/res/layout/bottom_sheet_legacy_standard.xml new file mode 100644 index 000000000..7bad55d9b --- /dev/null +++ b/core/src/main/res/layout/bottom_sheet_legacy_standard.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 4e1f637affd89fb4f67cb9cfecac58dc14203a4a Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jan 2024 13:44:03 +0100 Subject: [PATCH 25/73] feat(account): update AccountViewModel.kt --- .../net/ivpn/core/v2/account/AccountFragment.kt | 13 ++++++++++++- .../net/ivpn/core/v2/connect/ConnectFragment.kt | 7 +++++++ .../net/ivpn/core/v2/viewmodel/AccountViewModel.kt | 13 +++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt index e7e8c686a..2606f9401 100644 --- a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt @@ -41,6 +41,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.utils.ToastUtil import net.ivpn.core.databinding.FragmentAccountBinding +import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.MainActivity @@ -76,6 +77,7 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { IVPNApplication.appComponent.provideActivityComponent().create().inject(this) initViews() initToolbar() + updateSessionStatus() } override fun onResume() { @@ -133,10 +135,13 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { private fun initToolbar() { val navController = findNavController() val appBarConfiguration = AppBarConfiguration(navController.graph) - binding.toolbar.setupWithNavController(navController, appBarConfiguration) } + private fun updateSessionStatus() { + account.updateSessionStatus() + } + private fun copyAccountId() { account.username.get()?.let { userId -> val myClipboard = @@ -175,4 +180,10 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { override fun onDeviceLoggedOut() { } + + override fun onSessionUpdateSuccess() { + } + + override fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index a558a816c..d238616f7 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -57,6 +57,7 @@ import net.ivpn.core.databinding.FragmentConnectBinding import net.ivpn.core.rest.data.model.ServerLocation import net.ivpn.core.rest.data.model.ServerType import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.MainActivity import net.ivpn.core.v2.connect.createSession.ConnectionNavigator import net.ivpn.core.v2.connect.createSession.ConnectionState @@ -856,4 +857,10 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, override fun onDeviceLoggedOut() { openLoginScreen(true) } + + override fun onSessionUpdateSuccess() { + } + + override fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index a33e00457..7d63b02e2 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -34,6 +34,7 @@ import net.ivpn.core.common.qr.QRController import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.session.SessionListenerImpl import net.ivpn.core.common.utils.DateUtil +import net.ivpn.core.rest.data.wireguard.ErrorResponse import org.slf4j.LoggerFactory import javax.inject.Inject @@ -83,6 +84,14 @@ class AccountViewModel @Inject constructor( override fun onDeviceLoggedOut() { navigator?.onDeviceLoggedOut() } + + override fun onUpdateSuccess() { + navigator?.onSessionUpdateSuccess() + } + + override fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + navigator?.onSessionUpdateError(throwable, errorResponse) + } }) } @@ -282,6 +291,10 @@ class AccountViewModel @Inject constructor( fun onLogOutFailed() fun onDeviceLoggedOut() + + fun onSessionUpdateSuccess() + + fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) } enum class Type { From c76910a3a1b1b63a32f9cf43c03cfca64d3a1f84 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jan 2024 14:22:28 +0100 Subject: [PATCH 26/73] refactor: update SessionErrorResponse.kt --- core/src/main/java/net/ivpn/core/common/Mapper.kt | 6 +++--- .../java/net/ivpn/core/common/session/SessionController.kt | 4 ++-- .../net/ivpn/core/common/session/SessionListenerImpl.kt | 4 ++-- .../session/{SessionNewErrorData.kt => SessionErrorData.kt} | 4 ++-- .../{SessionNewErrorResponse.kt => SessionErrorResponse.kt} | 6 +++--- .../main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt | 4 ++-- .../main/java/net/ivpn/core/v2/connect/ConnectFragment.kt | 4 ++-- .../core/v2/connect/createSession/ConnectionNavigator.java | 4 ++-- .../v2/connect/createSession/CreateSessionFragment.java | 6 +++--- core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt | 4 ++-- .../main/java/net/ivpn/core/v2/login/LoginNavigator.java | 4 ++-- core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt | 6 +++--- core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt | 4 ++-- .../java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt | 4 ++-- .../java/net/ivpn/client/billing/BillingManagerWrapper.java | 4 ++-- 15 files changed, 34 insertions(+), 34 deletions(-) rename core/src/main/java/net/ivpn/core/rest/data/session/{SessionNewErrorData.kt => SessionErrorData.kt} (84%) rename core/src/main/java/net/ivpn/core/rest/data/session/{SessionNewErrorResponse.kt => SessionErrorResponse.kt} (86%) diff --git a/core/src/main/java/net/ivpn/core/common/Mapper.kt b/core/src/main/java/net/ivpn/core/common/Mapper.kt index ca299c33e..40909f07f 100644 --- a/core/src/main/java/net/ivpn/core/common/Mapper.kt +++ b/core/src/main/java/net/ivpn/core/common/Mapper.kt @@ -29,7 +29,7 @@ import net.ivpn.core.rest.data.ServersListResponse import net.ivpn.core.rest.data.model.AntiTracker import net.ivpn.core.rest.data.model.Port import net.ivpn.core.rest.data.model.Server -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse import java.util.* @@ -108,9 +108,9 @@ object Mapper { } @JvmStatic - fun sessionNewErrorResponseFrom(json: String?): SessionNewErrorResponse? { + fun sessionNewErrorResponseFrom(json: String?): SessionErrorResponse? { return if (json == null || json.isEmpty()) null else try { - Gson().fromJson(json, SessionNewErrorResponse::class.java) + Gson().fromJson(json, SessionErrorResponse::class.java) } catch (jsonSyntaxException: JsonSyntaxException) { null } catch (jsonSyntaxException: IllegalStateException) { diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index bda96351e..a24ad91a0 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -236,7 +236,7 @@ class SessionController @Inject constructor( } } - private fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { + private fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { for (listener in listeners) { listener.onCreateError(throwable, errorResponse) } @@ -365,7 +365,7 @@ class SessionController @Inject constructor( fun onCreateSuccess(response: SessionNewResponse) - fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) + fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) fun onUpdateSuccess() diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt index cee57a79e..857495780 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt @@ -23,7 +23,7 @@ package net.ivpn.core.common.session */ import net.ivpn.core.common.session.SessionController.* -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse @@ -37,7 +37,7 @@ open class SessionListenerImpl: SessionListener { override fun onCreateSuccess(response: SessionNewResponse) { } - override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } override fun onUpdateSuccess() { diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorData.kt similarity index 84% rename from core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt rename to core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorData.kt index 54de33efa..54acf2fc3 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorData.kt +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorData.kt @@ -25,7 +25,7 @@ package net.ivpn.core.rest.data.session; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -class SessionNewErrorData { +class SessionErrorData { @SerializedName("current_plan") @Expose @@ -60,7 +60,7 @@ class SessionNewErrorData { var upgradeToUrl: String = "" override fun toString(): String { - return "SessionNewErrorData(currentPlan='$currentPlan', deviceManagement=$deviceManagement, deviceManagementUrl='$deviceManagementUrl', limit=$limit, paymentMethod='$paymentMethod', upgradable=$upgradable, upgradeToPlan='$upgradeToPlan', upgradeToUrl='$upgradeToUrl')" + return "SessionErrorData(currentPlan='$currentPlan', deviceManagement=$deviceManagement, deviceManagementUrl='$deviceManagementUrl', limit=$limit, paymentMethod='$paymentMethod', upgradable=$upgradable, upgradeToPlan='$upgradeToPlan', upgradeToUrl='$upgradeToUrl')" } } diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt similarity index 86% rename from core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt rename to core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt index 31ad0b247..8f0916a37 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewErrorResponse.kt +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt @@ -25,7 +25,7 @@ package net.ivpn.core.rest.data.session; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -class SessionNewErrorResponse { +class SessionErrorResponse { @SerializedName("status") @Expose @@ -45,10 +45,10 @@ class SessionNewErrorResponse { @SerializedName("data") @Expose - var data:SessionNewErrorData? = null + var data:SessionErrorData? = null override fun toString(): String { - return "SessionNewErrorResponse(status=$status, message='$message', captchaId=$captchaId, captchaImage=$captchaImage, data=$data)" + return "SessionErrorResponse(status=$status, message='$message', captchaId=$captchaId, captchaImage=$captchaImage, data=$data)" } } diff --git a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt index bebd57cb7..b6f2d9588 100644 --- a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt @@ -39,7 +39,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.extension.setNavigationResultBoolean import net.ivpn.core.databinding.FragmentCaptchaBinding -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.login.LoginNavigator @@ -154,7 +154,7 @@ class CaptchaFragment : Fragment(), LoginNavigator { findNavController().popBackStack() } - override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { + override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index d238616f7..790625ffe 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -56,7 +56,7 @@ import net.ivpn.core.common.utils.ToastUtil import net.ivpn.core.databinding.FragmentConnectBinding import net.ivpn.core.rest.data.model.ServerLocation import net.ivpn.core.rest.data.model.ServerType -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.MainActivity import net.ivpn.core.v2.connect.createSession.ConnectionNavigator @@ -805,7 +805,7 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, }) } - override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { + override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { createSessionFragment = CreateSessionFragment(error) createSessionFragment.show(childFragmentManager, createSessionFragment.tag) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java index 2289c5291..a2e0621a4 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java @@ -22,7 +22,7 @@ along with the IVPN Android app. If not, see . */ -import net.ivpn.core.rest.data.session.SessionNewErrorResponse; +import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.v2.dialog.Dialogs; public interface ConnectionNavigator { @@ -37,7 +37,7 @@ public interface ConnectionNavigator { void logout(); - void openSessionLimitReachedDialogue(SessionNewErrorResponse error); + void openSessionLimitReachedDialogue(SessionErrorResponse error); void accountVerificationFailed(); diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index 80c8ef69b..0eda430c4 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -44,7 +44,7 @@ import net.ivpn.core.databinding.BottomSheetProBinding; import net.ivpn.core.databinding.BottomSheetDmStandardBinding; import net.ivpn.core.databinding.BottomSheetStandardBinding; -import net.ivpn.core.rest.data.session.SessionNewErrorResponse; +import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.v2.login.LoginFragment; import net.ivpn.core.common.billing.addfunds.Plan; @@ -54,9 +54,9 @@ public class CreateSessionFragment extends BottomSheetDialogFragment { private CreateSessionNavigator navigator; - private final SessionNewErrorResponse error; + private final SessionErrorResponse error; - public CreateSessionFragment(SessionNewErrorResponse error) { + public CreateSessionFragment(SessionErrorResponse error) { this.error = error; } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index 100f1d2a4..f9f37a5d1 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -43,7 +43,7 @@ import net.ivpn.core.common.billing.addfunds.Plan import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.databinding.FragmentLoginBinding -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.connect.createSession.CreateSessionFragment import net.ivpn.core.v2.connect.createSession.CreateSessionNavigator import net.ivpn.core.v2.dialog.DialogBuilder @@ -196,7 +196,7 @@ class LoginFragment : Fragment(), LoginNavigator, DialogBuilder.createNotificationDialog(context, dialog) } - override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { + override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { if (!isAdded) { return } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java b/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java index 4c48edb7a..eb4e74dd1 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginNavigator.java @@ -22,7 +22,7 @@ along with the IVPN Android app. If not, see . */ -import net.ivpn.core.rest.data.session.SessionNewErrorResponse; +import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.v2.dialog.Dialogs; public interface LoginNavigator { @@ -30,7 +30,7 @@ public interface LoginNavigator { void onLoginWithBlankAccount(); void onLoginWithInactiveAccount(); void onInvalidAccount(); - void openSessionLimitReachedDialogue(SessionNewErrorResponse error); + void openSessionLimitReachedDialogue(SessionErrorResponse error); void openCaptcha(); void openErrorDialogue(Dialogs dialogs); void openCustomErrorDialogue(String title, String message); diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt index f1abaf76f..6d43b3b3d 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt @@ -35,7 +35,7 @@ import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.session.SessionListenerImpl import net.ivpn.core.common.utils.ConnectivityUtil import net.ivpn.core.rest.Responses -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse import net.ivpn.core.v2.dialog.Dialogs import org.slf4j.LoggerFactory @@ -127,7 +127,7 @@ class LoginViewModel @Inject constructor( this@LoginViewModel.onSuccess(response) } - override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { LOGGER.error("Login process: ERROR", throwable) if (!ConnectivityUtil.isOnline(context)) { navigator?.openErrorDialogue(Dialogs.CONNECTION_ERROR) @@ -268,7 +268,7 @@ class LoginViewModel @Inject constructor( } } - private fun handleErrorResponse(errorResponse: SessionNewErrorResponse?) { + private fun handleErrorResponse(errorResponse: SessionErrorResponse?) { errorResponse?.let { } ?: kotlin.run { navigator?.openErrorDialogue(Dialogs.CREATE_SESSION_ERROR) diff --git a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt index d47817b19..03acdd942 100644 --- a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt @@ -38,7 +38,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.extension.setNavigationResultBoolean import net.ivpn.core.databinding.FragmentTfaBinding -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.connect.createSession.CreateSessionFragment import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs @@ -164,7 +164,7 @@ class TFAFragment : Fragment(), LoginNavigator { //Nothing to do } - override fun openSessionLimitReachedDialogue(error: SessionNewErrorResponse) { + override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt index 3fa0bb941..f5046ae7f 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt @@ -35,7 +35,7 @@ import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.utils.ConnectivityUtil import net.ivpn.core.common.utils.StringUtil import net.ivpn.core.rest.Responses -import net.ivpn.core.rest.data.session.SessionNewErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.connect.createSession.ConnectionNavigator @@ -258,7 +258,7 @@ class ConnectionViewModel @Inject constructor( } } - override fun onCreateError(throwable: Throwable?, errorResponse: SessionNewErrorResponse?) { + override fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { if (!ConnectivityUtil.isOnline(context)) { navigator?.openErrorDialog(Dialogs.CONNECTION_ERROR) return diff --git a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java index 46e62dd5e..fd51c14c3 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java @@ -45,7 +45,7 @@ import net.ivpn.core.rest.data.addfunds.AddFundsResponse; import net.ivpn.core.rest.data.addfunds.InitialPaymentRequestBody; import net.ivpn.core.rest.data.addfunds.InitialPaymentResponse; -import net.ivpn.core.rest.data.session.SessionNewErrorResponse; +import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.rest.data.session.SessionNewResponse; import net.ivpn.core.rest.data.wireguard.ErrorResponse; import net.ivpn.core.rest.requests.common.Request; @@ -249,7 +249,7 @@ public void onCreateSuccess(@NotNull SessionNewResponse response) { } @Override - public void onCreateError(@Nullable Throwable throwable, @Nullable SessionNewErrorResponse errorResponse) { + public void onCreateError(@Nullable Throwable throwable, @Nullable SessionErrorResponse errorResponse) { LOGGER.info("On create session Error: " + throwable + "/n" + errorResponse); sessionController.unSubscribe(this); setPurchaseState(CREATE_SESSION_ERROR); From c698d3c22b0ee2e3cf75a8c8705672adba735ca3 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jan 2024 14:38:04 +0100 Subject: [PATCH 27/73] refactor: update ErrorResponse.java --- .../main/java/net/ivpn/core/common/Mapper.kt | 2 +- .../core/common/session/SessionController.kt | 9 ++++---- .../common/session/SessionListenerImpl.kt | 3 +-- .../rest/data/wireguard/ErrorResponse.java | 23 +------------------ .../ivpn/core/v2/account/AccountFragment.kt | 4 ++-- .../ivpn/core/v2/connect/ConnectFragment.kt | 3 +-- .../core/v2/viewmodel/AccountViewModel.kt | 6 ++--- .../core/v2/viewmodel/ConnectionViewModel.kt | 3 +-- .../core/v2/viewmodel/ProtocolViewModel.java | 11 +++++---- .../vpn/controller/WireGuardBehavior.java | 3 --- .../client/billing/BillingManagerWrapper.java | 3 +-- 11 files changed, 21 insertions(+), 49 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/Mapper.kt b/core/src/main/java/net/ivpn/core/common/Mapper.kt index 40909f07f..c5bb4ece0 100644 --- a/core/src/main/java/net/ivpn/core/common/Mapper.kt +++ b/core/src/main/java/net/ivpn/core/common/Mapper.kt @@ -108,7 +108,7 @@ object Mapper { } @JvmStatic - fun sessionNewErrorResponseFrom(json: String?): SessionErrorResponse? { + fun sessionErrorResponseFrom(json: String?): SessionErrorResponse? { return if (json == null || json.isEmpty()) null else try { Gson().fromJson(json, SessionErrorResponse::class.java) } catch (jsonSyntaxException: JsonSyntaxException) { diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index a24ad91a0..13ae4e26d 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -37,7 +37,6 @@ import net.ivpn.core.rest.Responses import net.ivpn.core.rest.data.model.ServiceStatus import net.ivpn.core.rest.data.model.WireGuard import net.ivpn.core.rest.data.session.* -import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.rest.requests.common.Request import net.ivpn.core.rest.requests.common.RequestWrapper import net.ivpn.core.v2.login.LoginViewModel @@ -125,7 +124,7 @@ class SessionController @Inject constructor( override fun onError(error: String) { LOGGER.error("On create session error = $error") - val errorResponse = Mapper.sessionNewErrorResponseFrom(error) + val errorResponse = Mapper.sessionErrorResponseFrom(error) onCreateError(null, errorResponse) } }) @@ -159,7 +158,7 @@ class SessionController @Inject constructor( override fun onError(error: String) { LOGGER.error("Error while getting account status to see the confirmation$error") - val errorResponse = Mapper.errorResponseFrom(error) + val errorResponse = Mapper.sessionErrorResponseFrom(error) errorResponse?.let { if (it.status == Responses.SERVICE_IS_NOT_ACTIVE) { userPreference.putIsActive(false) @@ -248,7 +247,7 @@ class SessionController @Inject constructor( } } - private fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + private fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { for (listener in listeners) { listener.onUpdateError(throwable, errorResponse) } @@ -369,7 +368,7 @@ class SessionController @Inject constructor( fun onUpdateSuccess() - fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) + fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) fun onDeviceLoggedOut() } diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt index 857495780..dbc92680c 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt @@ -25,7 +25,6 @@ package net.ivpn.core.common.session import net.ivpn.core.common.session.SessionController.* import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse -import net.ivpn.core.rest.data.wireguard.ErrorResponse open class SessionListenerImpl: SessionListener { override fun onRemoveSuccess() { @@ -43,7 +42,7 @@ open class SessionListenerImpl: SessionListener { override fun onUpdateSuccess() { } - override fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } override fun onDeviceLoggedOut() { diff --git a/core/src/main/java/net/ivpn/core/rest/data/wireguard/ErrorResponse.java b/core/src/main/java/net/ivpn/core/rest/data/wireguard/ErrorResponse.java index 991a67483..d766d4151 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/wireguard/ErrorResponse.java +++ b/core/src/main/java/net/ivpn/core/rest/data/wireguard/ErrorResponse.java @@ -29,15 +29,10 @@ public class ErrorResponse { @SerializedName("status") @Expose private Integer status; + @SerializedName("message") @Expose private String message; - @SerializedName("captcha_id") - @Expose - private String captchaId = null; - @SerializedName("captcha_image") - @Expose - private String captchaImage = null; public Integer getStatus() { return status; @@ -55,22 +50,6 @@ public void setMessage(String message) { this.message = message; } - public String getCaptchaId() { - return captchaId; - } - - public void setCaptchaId(String captchaId) { - this.captchaId = captchaId; - } - - public String getCaptchaImage() { - return captchaImage; - } - - public void setCaptchaImage(String captchaImage) { - this.captchaImage = captchaImage; - } - @Override public String toString() { return "ErrorResponse{" + diff --git a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt index 2606f9401..57c93c7a2 100644 --- a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt @@ -41,7 +41,7 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.utils.ToastUtil import net.ivpn.core.databinding.FragmentAccountBinding -import net.ivpn.core.rest.data.wireguard.ErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.MainActivity @@ -184,6 +184,6 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { override fun onSessionUpdateSuccess() { } - override fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 790625ffe..510d97c8a 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -57,7 +57,6 @@ import net.ivpn.core.databinding.FragmentConnectBinding import net.ivpn.core.rest.data.model.ServerLocation import net.ivpn.core.rest.data.model.ServerType import net.ivpn.core.rest.data.session.SessionErrorResponse -import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.MainActivity import net.ivpn.core.v2.connect.createSession.ConnectionNavigator import net.ivpn.core.v2.connect.createSession.ConnectionState @@ -861,6 +860,6 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, override fun onSessionUpdateSuccess() { } - override fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index 7d63b02e2..507263d97 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -34,7 +34,7 @@ import net.ivpn.core.common.qr.QRController import net.ivpn.core.common.session.SessionController import net.ivpn.core.common.session.SessionListenerImpl import net.ivpn.core.common.utils.DateUtil -import net.ivpn.core.rest.data.wireguard.ErrorResponse +import net.ivpn.core.rest.data.session.SessionErrorResponse import org.slf4j.LoggerFactory import javax.inject.Inject @@ -89,7 +89,7 @@ class AccountViewModel @Inject constructor( navigator?.onSessionUpdateSuccess() } - override fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { navigator?.onSessionUpdateError(throwable, errorResponse) } }) @@ -294,7 +294,7 @@ class AccountViewModel @Inject constructor( fun onSessionUpdateSuccess() - fun onSessionUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) + fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) } enum class Type { diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt index f5046ae7f..09131747c 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ConnectionViewModel.kt @@ -37,7 +37,6 @@ import net.ivpn.core.common.utils.StringUtil import net.ivpn.core.rest.Responses import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.rest.data.session.SessionNewResponse -import net.ivpn.core.rest.data.wireguard.ErrorResponse import net.ivpn.core.v2.connect.createSession.ConnectionNavigator import net.ivpn.core.v2.connect.createSession.ConnectionState import net.ivpn.core.v2.dialog.Dialogs @@ -285,7 +284,7 @@ class ConnectionViewModel @Inject constructor( override fun onUpdateSuccess() { } - override fun onUpdateError(throwable: Throwable?, errorResponse: ErrorResponse?) { + override fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { errorResponse?.let { if (it.status == Responses.SESSION_NOT_FOUND){ navigator?.logout() diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/ProtocolViewModel.java b/core/src/main/java/net/ivpn/core/v2/viewmodel/ProtocolViewModel.java index 666ac9005..419aa43de 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/ProtocolViewModel.java +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/ProtocolViewModel.java @@ -38,7 +38,7 @@ import net.ivpn.core.common.prefs.Settings; import net.ivpn.core.rest.Responses; import net.ivpn.core.rest.data.model.Port; -import net.ivpn.core.rest.data.wireguard.ErrorResponse; +import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.v2.protocol.ProtocolNavigator; import net.ivpn.core.v2.dialog.Dialogs; import net.ivpn.core.v2.protocol.dialog.WireGuardInfo; @@ -236,17 +236,18 @@ private void onGeneratingError(String error, Throwable throwable) { } } - ErrorResponse errorResponse = Mapper.errorResponseFrom(error); - if (error == null || errorResponse.getStatus() == null || errorResponse.getMessage() == null) { + SessionErrorResponse errorResponse = Mapper.sessionErrorResponseFrom(error); + if (error == null) { navigator.openDialogueError(Dialogs.WG_UPLOADING_KEY_ERROR); return; + } else { + errorResponse.getMessage(); } if (errorResponse.getStatus() == Responses.WIREGUARD_KEY_LIMIT_REACHED) { navigator.openDialogueError(Dialogs.WG_MAXIMUM_KEYS_REACHED); } else { - navigator.openCustomDialogueError(context.getString(R.string.dialogs_error) + errorResponse.getStatus(), - errorResponse.getMessage() != null ? errorResponse.getMessage() : ""); + navigator.openCustomDialogueError(context.getString(R.string.dialogs_error) + errorResponse.getStatus(), errorResponse.getMessage()); } } diff --git a/core/src/main/java/net/ivpn/core/vpn/controller/WireGuardBehavior.java b/core/src/main/java/net/ivpn/core/vpn/controller/WireGuardBehavior.java index 3dabf64fb..473555ad8 100644 --- a/core/src/main/java/net/ivpn/core/vpn/controller/WireGuardBehavior.java +++ b/core/src/main/java/net/ivpn/core/vpn/controller/WireGuardBehavior.java @@ -37,15 +37,12 @@ import com.wireguard.android.model.Tunnel; import net.ivpn.core.IVPNApplication; -import net.ivpn.core.R; import net.ivpn.core.common.Mapper; import net.ivpn.core.common.multihop.MultiHopController; -import net.ivpn.core.common.pinger.OnFastestServerDetectorListener; import net.ivpn.core.common.pinger.PingProvider; import net.ivpn.core.rest.data.model.ServerType; import net.ivpn.core.common.prefs.ServersRepository; import net.ivpn.core.common.utils.DateUtil; -import net.ivpn.core.common.utils.ToastUtil; import net.ivpn.core.rest.Responses; import net.ivpn.core.rest.data.model.Server; import net.ivpn.core.rest.data.wireguard.ErrorResponse; diff --git a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java index fd51c14c3..123606c8a 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java @@ -47,7 +47,6 @@ import net.ivpn.core.rest.data.addfunds.InitialPaymentResponse; import net.ivpn.core.rest.data.session.SessionErrorResponse; import net.ivpn.core.rest.data.session.SessionNewResponse; -import net.ivpn.core.rest.data.wireguard.ErrorResponse; import net.ivpn.core.rest.requests.common.Request; import net.ivpn.core.rest.requests.common.RequestWrapper; @@ -298,7 +297,7 @@ public void onUpdateSuccess() { } @Override - public void onUpdateError(@Nullable Throwable throwable, @Nullable ErrorResponse errorResponse) { + public void onUpdateError(@Nullable Throwable throwable, @Nullable SessionErrorResponse errorResponse) { LOGGER.info("On create session Error: " + throwable + "/n" + errorResponse); sessionController.unSubscribe(this); setPurchaseState(UPDATE_SESSION_ERROR); From 32e698e78e8e274494ad86fffc74ace4ff79fb84 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jan 2024 16:25:00 +0100 Subject: [PATCH 28/73] feat(account): update AccountFragment.kt --- .../core/common/session/SessionController.kt | 1 - .../ivpn/core/v2/account/AccountFragment.kt | 21 +++++++++++++------ .../ivpn/core/v2/connect/ConnectFragment.kt | 6 ------ .../core/v2/viewmodel/AccountViewModel.kt | 12 ----------- core/src/main/res/navigation/nav_graph.xml | 7 +++++++ 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index 13ae4e26d..f6ad62bc6 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -165,7 +165,6 @@ class SessionController @Inject constructor( } if ((it.status == Responses.SESSION_NOT_FOUND)) { clearSessionData() - onRemoveSuccess() onDeviceLoggedOut() } } diff --git a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt index 57c93c7a2..e114935eb 100644 --- a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt @@ -45,6 +45,7 @@ import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.MainActivity +import net.ivpn.core.v2.connect.ConnectFragmentDirections import net.ivpn.core.v2.signup.SignUpController import net.ivpn.core.v2.viewmodel.AccountViewModel import org.slf4j.LoggerFactory @@ -83,6 +84,9 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { override fun onResume() { super.onResume() account.onResume() + if (!account.authenticated.get()) { + openHomeScreen() + } } override fun onStart() { @@ -172,6 +176,16 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { navigate(action) } + private fun openLoginScreen() { + val action = AccountFragmentDirections.actionAccountFragmentToLoginFragment(true) + navigate(action) + } + + private fun openHomeScreen() { + val action = AccountFragmentDirections.actionAccountFragmentToConnectFragment() + navigate(action) + } + override fun onLogOutFailed() { DialogBuilder.createOptionDialog(requireContext(), Dialogs.FORCE_LOGOUT) { account.forceLogout() @@ -179,11 +193,6 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { } override fun onDeviceLoggedOut() { - } - - override fun onSessionUpdateSuccess() { - } - - override fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { + openLoginScreen() } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 510d97c8a..5c86a915b 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -856,10 +856,4 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, override fun onDeviceLoggedOut() { openLoginScreen(true) } - - override fun onSessionUpdateSuccess() { - } - - override fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { - } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index 507263d97..24d69f06c 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -84,14 +84,6 @@ class AccountViewModel @Inject constructor( override fun onDeviceLoggedOut() { navigator?.onDeviceLoggedOut() } - - override fun onUpdateSuccess() { - navigator?.onSessionUpdateSuccess() - } - - override fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { - navigator?.onSessionUpdateError(throwable, errorResponse) - } }) } @@ -291,10 +283,6 @@ class AccountViewModel @Inject constructor( fun onLogOutFailed() fun onDeviceLoggedOut() - - fun onSessionUpdateSuccess() - - fun onSessionUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) } enum class Type { diff --git a/core/src/main/res/navigation/nav_graph.xml b/core/src/main/res/navigation/nav_graph.xml index 4939c11df..bf4b1d927 100644 --- a/core/src/main/res/navigation/nav_graph.xml +++ b/core/src/main/res/navigation/nav_graph.xml @@ -160,6 +160,13 @@ + + Date: Thu, 25 Jan 2024 10:49:06 +0100 Subject: [PATCH 29/73] feat(account): update AccountFragment.kt --- .../main/java/net/ivpn/core/v2/account/AccountFragment.kt | 6 ++++-- .../main/java/net/ivpn/core/v2/connect/ConnectFragment.kt | 3 +++ .../java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt | 8 ++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt index e114935eb..f02905805 100644 --- a/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/account/AccountFragment.kt @@ -41,11 +41,9 @@ import net.ivpn.core.common.extension.findNavControllerSafely import net.ivpn.core.common.extension.navigate import net.ivpn.core.common.utils.ToastUtil import net.ivpn.core.databinding.FragmentAccountBinding -import net.ivpn.core.rest.data.session.SessionErrorResponse import net.ivpn.core.v2.dialog.DialogBuilder import net.ivpn.core.v2.dialog.Dialogs import net.ivpn.core.v2.MainActivity -import net.ivpn.core.v2.connect.ConnectFragmentDirections import net.ivpn.core.v2.signup.SignUpController import net.ivpn.core.v2.viewmodel.AccountViewModel import org.slf4j.LoggerFactory @@ -195,4 +193,8 @@ class AccountFragment : Fragment(), AccountViewModel.AccountNavigator { override fun onDeviceLoggedOut() { openLoginScreen() } + + override fun onSessionStatusUpdate() { + onResume() + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 5c86a915b..5cb31ca58 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -856,4 +856,7 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, override fun onDeviceLoggedOut() { openLoginScreen(true) } + + override fun onSessionStatusUpdate() { + } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index 24d69f06c..339f8878e 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -76,14 +76,16 @@ class AccountViewModel @Inject constructor( override fun onRemoveSuccess() { onRemoveSessionSuccess() } - override fun onRemoveError() { onRemoveSessionFailed() } - override fun onDeviceLoggedOut() { navigator?.onDeviceLoggedOut() } + + override fun onUpdateSuccess() { + navigator?.onSessionStatusUpdate() + } }) } @@ -283,6 +285,8 @@ class AccountViewModel @Inject constructor( fun onLogOutFailed() fun onDeviceLoggedOut() + + fun onSessionStatusUpdate() } enum class Type { From e287fee782996f030fdfbb70a5a5591c9a9b8654 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 25 Jan 2024 14:33:23 +0100 Subject: [PATCH 30/73] chore: update app version and build number --- core/build.gradle | 4 ++-- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 4 ++-- store/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 1d4207dcd..4df597eee 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,8 +30,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 129 - versionName "2.10.6" + versionCode 130 + versionName "2.10.7" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 4f585e1a6..d4acc92a5 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 129 - versionName "2.10.6" + versionCode 130 + versionName "2.10.7" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 5c60ef05e..0a545d2fd 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 129 - versionName "2.10.6" + versionCode 130 + versionName "2.10.7" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/site/build.gradle b/site/build.gradle index 46c6119b7..4766f0bfe 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 129 - versionName "2.10.6" + versionCode 130 + versionName "2.10.7" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/store/build.gradle b/store/build.gradle index c81b62dca..4a7b0a26e 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,8 +32,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 129 - versionName "2.10.6" + versionCode 130 + versionName "2.10.7" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] From b78ac988fe02de9105fdcc756a5fcf2f9f016a1c Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 30 Jan 2024 15:04:05 +0100 Subject: [PATCH 31/73] feat(account): update strings.xml --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 329196ebe..9b1451da5 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -350,7 +350,7 @@ Session limit You\'ve reached the session limit, force login to logout of all other devices. - You have exceeded the maximum number of sessions + You\'ve reached the maximum number of connected devices Force login Log out from all devices Retry From 85f6a7b23545eefff195382332551289e2da7304 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 31 Jan 2024 13:09:56 +0100 Subject: [PATCH 32/73] feat(account): update SessionErrorResponse.kt --- .../net/ivpn/core/common/session/SessionController.kt | 10 ++++------ .../ivpn/core/common/session/SessionListenerImpl.kt | 6 ------ .../core/rest/data/session/SessionErrorResponse.kt | 4 +++- .../java/net/ivpn/core/v2/connect/ConnectFragment.kt | 3 +-- .../v2/connect/createSession/ConnectionNavigator.java | 10 ---------- .../main/java/net/ivpn/core/v2/login/LoginFragment.kt | 3 +-- .../net/ivpn/core/v2/viewmodel/AccountViewModel.kt | 8 +++++--- 7 files changed, 14 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index f6ad62bc6..d91da4e65 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -40,6 +40,7 @@ import net.ivpn.core.rest.data.session.* import net.ivpn.core.rest.requests.common.Request import net.ivpn.core.rest.requests.common.RequestWrapper import net.ivpn.core.v2.login.LoginViewModel +import net.ivpn.core.v2.viewmodel.AccountViewModel import net.ivpn.core.v2.viewmodel.ViewModelCleaner import net.ivpn.core.vpn.Protocol import net.ivpn.core.vpn.ProtocolController @@ -125,6 +126,9 @@ class SessionController @Inject constructor( override fun onError(error: String) { LOGGER.error("On create session error = $error") val errorResponse = Mapper.sessionErrorResponseFrom(error) + if (errorResponse != null) { + errorResponse.isAccountNewStyle = AccountViewModel.isNewStyleAccount(body.username) + } onCreateError(null, errorResponse) } }) @@ -358,17 +362,11 @@ class SessionController @Inject constructor( interface SessionListener { fun onRemoveSuccess() - fun onRemoveError() - fun onCreateSuccess(response: SessionNewResponse) - fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) - fun onUpdateSuccess() - fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) - fun onDeviceLoggedOut() } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt index dbc92680c..521981c36 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionListenerImpl.kt @@ -29,22 +29,16 @@ import net.ivpn.core.rest.data.session.SessionNewResponse open class SessionListenerImpl: SessionListener { override fun onRemoveSuccess() { } - override fun onRemoveError() { } - override fun onCreateSuccess(response: SessionNewResponse) { } - override fun onCreateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } - override fun onUpdateSuccess() { } - override fun onUpdateError(throwable: Throwable?, errorResponse: SessionErrorResponse?) { } - override fun onDeviceLoggedOut() { } } \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt index 8f0916a37..2ae02f25a 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionErrorResponse.kt @@ -47,8 +47,10 @@ class SessionErrorResponse { @Expose var data:SessionErrorData? = null + var isAccountNewStyle: Boolean = true + override fun toString(): String { - return "SessionErrorResponse(status=$status, message='$message', captchaId=$captchaId, captchaImage=$captchaImage, data=$data)" + return "SessionErrorResponse(status=$status, message='$message', captchaId=$captchaId, captchaImage=$captchaImage, data=$data, isAccountNewStyle=$isAccountNewStyle)" } } diff --git a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt index 5cb31ca58..93060a0d5 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/connect/ConnectFragment.kt @@ -805,8 +805,7 @@ class ConnectFragment : Fragment(), MultiHopViewModel.MultiHopNavigator, } override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { - createSessionFragment = - CreateSessionFragment(error) + createSessionFragment = CreateSessionFragment(error) createSessionFragment.show(childFragmentManager, createSessionFragment.tag) } diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java index a2e0621a4..a25f2274e 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/ConnectionNavigator.java @@ -26,24 +26,14 @@ import net.ivpn.core.v2.dialog.Dialogs; public interface ConnectionNavigator { - void askConnectionPermission(); - void onAuthFailed(); - void onTimeOut(); - void notifyAnotherPortUsedToConnect(); - void logout(); - void openSessionLimitReachedDialogue(SessionErrorResponse error); - void accountVerificationFailed(); - void openNoNetworkDialog(); - void openErrorDialog(Dialogs dialogs); - void onChangeConnectionStatus(ConnectionState state); } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index f9f37a5d1..7ed36a252 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -200,8 +200,7 @@ class LoginFragment : Fragment(), LoginNavigator, if (!isAdded) { return } - createSessionFragment = - CreateSessionFragment(error) + createSessionFragment = CreateSessionFragment(error) createSessionFragment?.let { it.show(childFragmentManager, it.tag) } diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt index 339f8878e..62841f6a3 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/AccountViewModel.kt @@ -46,6 +46,10 @@ class AccountViewModel @Inject constructor( companion object { private val LOGGER = LoggerFactory.getLogger(AccountViewModel::class.java) + + fun isNewStyleAccount(username: String): Boolean { + return username.startsWith("i-") + } } val dataLoading = ObservableBoolean() @@ -182,9 +186,7 @@ class AccountViewModel @Inject constructor( } fun isAccountNewStyle(): Boolean { - return paymentMethod?.let { - it == "prepaid" - } ?: false + return isNewStyleAccount(username.get().toString()) } private fun clearLocalCache() { From 13db3c12aae23a242fae6705e9c6a4c734d48e8b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 31 Jan 2024 13:13:19 +0100 Subject: [PATCH 33/73] feat(account): update CreateSessionFragment.java --- .../core/v2/connect/createSession/CreateSessionFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java index 0eda430c4..d1b452a78 100644 --- a/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java +++ b/core/src/main/java/net/ivpn/core/v2/connect/createSession/CreateSessionFragment.java @@ -78,7 +78,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Plan plan = Plan.Companion.getPlanByProductName(Objects.requireNonNull(error.getData()).getCurrentPlan()); boolean deviceManagement = Objects.requireNonNull(error.getData()).getDeviceManagement(); - boolean isAccountNewStyle = Objects.requireNonNull(error.getData()).getPaymentMethod().equals("prepaid"); + boolean isAccountNewStyle = error.isAccountNewStyle(); // Device Management enabled, Pro plan if (deviceManagement && plan.equals(Plan.PRO) && isAccountNewStyle) { From f2c17269342325826731e0b585254e76e39276c1 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 1 Feb 2024 17:32:18 +0100 Subject: [PATCH 34/73] feat(api): update session API calls timeout --- .../java/net/ivpn/core/common/session/SessionController.kt | 4 ++-- .../main/java/net/ivpn/core/rest/requests/common/Request.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt index 12790b0a1..7102c8fb7 100644 --- a/core/src/main/java/net/ivpn/core/common/session/SessionController.kt +++ b/core/src/main/java/net/ivpn/core/common/session/SessionController.kt @@ -109,7 +109,7 @@ class SessionController @Inject constructor( } private fun innerCreateSession(body: SessionNewRequestBody, keys: Keypair?) { - sessionNewRequest = Request(settings, clientFactory, serversRepository, Request.Duration.SHORT, RequestWrapper.IpMode.IPv4) + sessionNewRequest = Request(settings, clientFactory, serversRepository, Request.Duration.LONG, RequestWrapper.IpMode.IPv4) sessionNewRequest?.start({ api: IVPNApi -> api.newSession(body) }, object : RequestListener { @@ -179,7 +179,7 @@ class SessionController @Inject constructor( val token = userPreference.getSessionToken() val requestBody = DeleteSessionRequestBody(token) - deleteSessionRequest = Request(settings, clientFactory, serversRepository, Request.Duration.SHORT, RequestWrapper.IpMode.IPv4) + deleteSessionRequest = Request(settings, clientFactory, serversRepository, Request.Duration.LONG, RequestWrapper.IpMode.IPv4) deleteSessionRequest?.start({ api: IVPNApi -> api.deleteSession(requestBody) }, object : RequestListener { diff --git a/core/src/main/java/net/ivpn/core/rest/requests/common/Request.java b/core/src/main/java/net/ivpn/core/rest/requests/common/Request.java index 3ad49d458..b728caa1d 100644 --- a/core/src/main/java/net/ivpn/core/rest/requests/common/Request.java +++ b/core/src/main/java/net/ivpn/core/rest/requests/common/Request.java @@ -33,7 +33,7 @@ public class Request { public Request(Settings settings, HttpClientFactory httpClientFactory, ServersRepository serversRepository, Duration duration, RequestWrapper.IpMode mode) { - int timeOut = duration == Duration.SHORT ? 10 : 30; + int timeOut = duration == Duration.SHORT ? 15 : 45; requestWrapper = new RequestWrapper(settings, httpClientFactory, serversRepository, timeOut, mode); } From ec8de077b1ea4f266678e5b363ce079ffa8dc0db Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 2 Feb 2024 12:50:45 +0100 Subject: [PATCH 35/73] feat(account): update strings.xml --- core/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9b1451da5..5ed3eb741 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -338,8 +338,8 @@ IVPN will automatically start when you connect to an untrusted Wi-Fi network - Server unreachable - Unable to contact server to log out. Please check Internet connectivity. Do you want to force log out? This device will continue to count towards your device limit. + Unable to contact server to log out + Please check Internet connectivity. Do you want to force log out? This device will continue to count towards your device limit. Force log out Cancel From 0d11161cd4bb1599c401ecdfb7b4a56c927bd031 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 12 Feb 2024 13:46:16 +0100 Subject: [PATCH 36/73] docs: update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d370bebc8..05dc4004d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. +## Version 2.10.7 - 2024-02-12 + +[NEW] Device Management +[IMPROVED] Increased timeout for API requests + +[Download IVPN Client v2.10.7](https://www.ivpn.net/releases/android/IVPNv2.10.7site.apk) +SHA256: e091ee87d73eda39036854ca02be2c0451502730043fe39a8242403124965ceb + ## Version 2.10.6 - 2023-12-18 [FIXED] Crash when opening the app on F-Droid From a414e968b5c749900cf33f4922024359cf9ef659 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 14 Feb 2024 15:25:46 +0100 Subject: [PATCH 37/73] feat(payments): support for PURCHASE_PENDING state --- .../ivpn/client/billing/BillingActivity.java | 9 +++++ .../client/billing/BillingManagerWrapper.java | 20 +++++++--- .../ivpn/client/billing/BillingNavigator.java | 2 + .../ivpn/client/billing/BillingViewModel.java | 38 +++++++++---------- .../client/signup/SignUpPeriodFragment.kt | 9 +++++ .../client/signup/SignUpProductFragment.kt | 9 +++++ .../net/ivpn/client/signup/SignUpViewModel.kt | 15 +++++++- 7 files changed, 76 insertions(+), 26 deletions(-) diff --git a/store/src/main/java/net/ivpn/client/billing/BillingActivity.java b/store/src/main/java/net/ivpn/client/billing/BillingActivity.java index 1227c7b60..3d79df4e1 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingActivity.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingActivity.java @@ -107,6 +107,15 @@ public void createPurchaseErrorDialog(String errorCode, String errorMessage) { }); } + @Override + public void createDialog(String title, String message) { + DialogBuilder.createFullCustomNotificationDialog(this, + title, + message, dialog -> { + BillingActivity.this.finish(); + }); + } + @Override public void onAccountCreated() { finish(); diff --git a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java index 123606c8a..cc5ab410c 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java @@ -60,12 +60,14 @@ import javax.inject.Inject; +import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.ADD_FUNDS_ERROR; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.CREATE_SESSION; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.CREATE_SESSION_ERROR; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.INITIAL_PAYMENT; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.INITIAL_PAYMENT_ERROR; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.UPDATE_SESSION; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.UPDATE_SESSION_ERROR; +import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.PURCHASE_PENDING; @BillingScope public class BillingManagerWrapper { @@ -130,8 +132,15 @@ public void onPurchasesUpdated(List purchases) { && ConsumableProducts.INSTANCE.getConsumableSKUs().contains(purchase.getProducts().get(0))) { billingManager.consumePurchase(purchase); } + + if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) { + setPurchaseState(PURCHASE_PENDING); + } + + if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) { + startValidatingActivity(purchase); + } } - startValidatingActivity(purchases.get(0)); } @Override @@ -268,18 +277,18 @@ public void onSuccess(AddFundsResponse response) { if (response.getStatus() == Responses.SUCCESS) { updateSession(); } else { - setPurchaseState(INITIAL_PAYMENT_ERROR); + setPurchaseState(ADD_FUNDS_ERROR); } } @Override public void onError(Throwable throwable) { - setPurchaseState(INITIAL_PAYMENT_ERROR); + setPurchaseState(ADD_FUNDS_ERROR); } @Override public void onError(String string) { - setPurchaseState(INITIAL_PAYMENT_ERROR); + setPurchaseState(ADD_FUNDS_ERROR); } }); } @@ -346,6 +355,7 @@ public enum PurchaseState { CREATE_SESSION_ERROR, UPDATE_SESSION, UPDATE_SESSION_ERROR, - ADD_FUNDS_ERROR + ADD_FUNDS_ERROR, + PURCHASE_PENDING } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/billing/BillingNavigator.java b/store/src/main/java/net/ivpn/client/billing/BillingNavigator.java index f2f661b58..4f8f72281 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingNavigator.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingNavigator.java @@ -32,6 +32,8 @@ public interface BillingNavigator { void createPurchaseErrorDialog(String errorCode, String errorMessage); + void createDialog(String title, String message); + void onAccountCreated(); void onAddFundsFinish(); diff --git a/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java b/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java index 34f55c9a7..99f8be412 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java @@ -72,39 +72,39 @@ public void onInitStateChanged(boolean isInit, int error) { public void onPurchaseStateChanged(BillingManagerWrapper.PurchaseState state) { LOGGER.info("PurchaseState = " + state); switch (state) { - case NONE: - dataLoading.set(false); - break; - case INITIAL_PAYMENT: - case PURCHASING: - case VALIDATING: + case NONE -> dataLoading.set(false); + case INITIAL_PAYMENT, PURCHASING, VALIDATING -> { dataLoading.set(true); processDescription.set(getString(R.string.billing_validating)); - break; - case CREATE_ACCOUNT: + } + case CREATE_ACCOUNT -> { dataLoading.set(true); processDescription.set(getString(R.string.billing_creating_account)); - break; - case CREATE_SESSION: + } + case CREATE_SESSION -> { dataLoading.set(true); processDescription.set(getString(R.string.billing_creating_new_session)); - break; - case INITIAL_PAYMENT_ERROR: + } + case INITIAL_PAYMENT_ERROR -> { dataLoading.set(false); navigator.createPurchaseErrorDialog("", "There was an error while creating your account. Contact our support or reopen the application to try again."); - break; - case ADD_FUNDS_ERROR: + } + case ADD_FUNDS_ERROR -> { dataLoading.set(false); navigator.createPurchaseErrorDialog("", "There was an error while adding funds to your account. Contact our support or reopen the application to try again."); - break; - case UPDATE_SESSION_ERROR: + } + case PURCHASE_PENDING -> { + dataLoading.set(false); + navigator.createDialog("Pending payment", "Payment is pending for approval. We will complete the transaction as soon as payment is approved."); + } + case UPDATE_SESSION_ERROR -> { dataLoading.set(false); navigator.createPurchaseErrorDialog("", "There was an error while updating your session. Contact our support or reopen the application to try again."); - break; - case DONE: + } + case DONE -> { dataLoading.set(false); navigator.onSuccessBilling(); - break; + } } } diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt b/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt index e26724655..8d7bb9bac 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt @@ -137,4 +137,13 @@ class SignUpPeriodFragment : Fragment(), SignUpViewModel.SignUpNavigator { } } } + + override fun createDialog(title: String?, message: String?) { + if (activity != null) { + DialogBuilder.createFullCustomNotificationDialog(activity, title, + message) { + findNavControllerSafely()?.popBackStack() + } + } + } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt b/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt index 908d728fa..77b77b000 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt @@ -121,4 +121,13 @@ class SignUpProductFragment : Fragment(), SignUpViewModel.SignUpNavigator { } } } + + override fun createDialog(title: String?, message: String?) { + if (activity != null) { + DialogBuilder.createFullCustomNotificationDialog(activity, title, + message) { + findNavControllerSafely()?.popBackStack() + } + } + } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt b/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt index fc453e17b..511598453 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt @@ -51,9 +51,8 @@ import net.ivpn.core.rest.requests.common.Request import net.ivpn.core.rest.requests.common.RequestWrapper import net.ivpn.core.v2.signup.SignUpController import org.slf4j.LoggerFactory -import java.util.* +import java.util.Calendar import javax.inject.Inject -import kotlin.collections.ArrayList import kotlin.math.floor @BillingScope @@ -360,6 +359,16 @@ class SignUpViewModel @Inject constructor( } override fun onPurchaseStateChanged(state: BillingManagerWrapper.PurchaseState?) { + when (state) { + BillingManagerWrapper.PurchaseState.PURCHASE_PENDING -> { + navigator?.createDialog( + "Pending payment", + "Payment is pending for approval. We will complete the transaction as soon as payment is approved." + ) + } + + else -> {} + } } private fun handleError(error: Int) { @@ -421,5 +430,7 @@ class SignUpViewModel @Inject constructor( fun onAddFundsFinish() fun onGoogleConnectFailure() + + fun createDialog(title: String?, message: String?) } } \ No newline at end of file From 520c0823b8a7217399dc62db164063a81d87a679 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 14 Feb 2024 16:43:38 +0100 Subject: [PATCH 38/73] chore: update app version and build number --- core/build.gradle | 4 ++-- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 4 ++-- store/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 4df597eee..992e5fc64 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,8 +30,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 130 - versionName "2.10.7" + versionCode 131 + versionName "2.10.8" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index d4acc92a5..a6aa94eba 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 130 - versionName "2.10.7" + versionCode 131 + versionName "2.10.8" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 0a545d2fd..60fd4adb4 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 33 - versionCode 130 - versionName "2.10.7" + versionCode 131 + versionName "2.10.8" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/site/build.gradle b/site/build.gradle index 4766f0bfe..5fe6ca81b 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 130 - versionName "2.10.7" + versionCode 131 + versionName "2.10.8" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/store/build.gradle b/store/build.gradle index 4a7b0a26e..ab951cc10 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,8 +32,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 21 targetSdkVersion 33 - versionCode 130 - versionName "2.10.7" + versionCode 131 + versionName "2.10.8" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] From 80e8e88f0533029a42eaf44f37d037fc728914f7 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 19 Feb 2024 12:25:56 +0100 Subject: [PATCH 39/73] refactor: update AndroidManifest.xml --- core/src/main/AndroidManifest.xml | 2 ++ fdroid/src/main/AndroidManifest.xml | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 82047bb81..34fdb9a39 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -52,6 +52,8 @@ tools:overrideLibrary="com.google.zxing.client.android" tools:ignore="GoogleAppIndexingWarning, HardcodedDebugMode"> + + diff --git a/fdroid/src/main/AndroidManifest.xml b/fdroid/src/main/AndroidManifest.xml index 9edc7a57f..c792adb89 100644 --- a/fdroid/src/main/AndroidManifest.xml +++ b/fdroid/src/main/AndroidManifest.xml @@ -20,10 +20,6 @@ android:hasFragileUserData="false" tools:ignore="HardcodedDebugMode"> - - \ No newline at end of file From e14e03bca26b63ff555a55b4d779995acd9f3ec6 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 21 Feb 2024 18:19:54 +0100 Subject: [PATCH 40/73] feat(payments): support for INITIAL_PAYMENT_PENDING state --- .../ivpn/client/billing/BillingManagerWrapper.java | 13 ++++++++++--- .../net/ivpn/client/billing/BillingViewModel.java | 6 +++++- .../net/ivpn/client/signup/SignUpPeriodFragment.kt | 9 +++++++++ .../net/ivpn/client/signup/SignUpProductFragment.kt | 9 +++++++++ .../java/net/ivpn/client/signup/SignUpViewModel.kt | 11 ++++++++++- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java index cc5ab410c..1ab84b212 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingManagerWrapper.java @@ -67,7 +67,8 @@ import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.INITIAL_PAYMENT_ERROR; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.UPDATE_SESSION; import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.UPDATE_SESSION_ERROR; -import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.PURCHASE_PENDING; +import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.PAYMENT_PENDING; +import static net.ivpn.client.billing.BillingManagerWrapper.PurchaseState.INITIAL_PAYMENT_PENDING; @BillingScope public class BillingManagerWrapper { @@ -134,7 +135,12 @@ public void onPurchasesUpdated(List purchases) { } if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) { - setPurchaseState(PURCHASE_PENDING); + String sessionToken = userPreference.getSessionToken(); + if (sessionToken.isEmpty()) { + setPurchaseState(INITIAL_PAYMENT_PENDING); + } else { + setPurchaseState(PAYMENT_PENDING); + } } if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) { @@ -356,6 +362,7 @@ public enum PurchaseState { UPDATE_SESSION, UPDATE_SESSION_ERROR, ADD_FUNDS_ERROR, - PURCHASE_PENDING + PAYMENT_PENDING, + INITIAL_PAYMENT_PENDING } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java b/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java index 99f8be412..51aef6d14 100644 --- a/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java +++ b/store/src/main/java/net/ivpn/client/billing/BillingViewModel.java @@ -93,7 +93,11 @@ public void onPurchaseStateChanged(BillingManagerWrapper.PurchaseState state) { dataLoading.set(false); navigator.createPurchaseErrorDialog("", "There was an error while adding funds to your account. Contact our support or reopen the application to try again."); } - case PURCHASE_PENDING -> { + case PAYMENT_PENDING -> { + dataLoading.set(false); + navigator.createDialog("Pending payment", "Payment is pending for approval. We will complete the transaction as soon as payment is approved."); + } + case INITIAL_PAYMENT_PENDING -> { dataLoading.set(false); navigator.createDialog("Pending payment", "Payment is pending for approval. We will complete the transaction as soon as payment is approved."); } diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt b/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt index 8d7bb9bac..7e9ff9044 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpPeriodFragment.kt @@ -146,4 +146,13 @@ class SignUpPeriodFragment : Fragment(), SignUpViewModel.SignUpNavigator { } } } + + override fun createInitialDialog(title: String?, message: String?) { + if (activity != null) { + DialogBuilder.createFullCustomNotificationDialog(activity, title, + message) { + findNavControllerSafely()?.navigate(net.ivpn.core.R.id.connectFragment) + } + } + } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt b/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt index 77b77b000..12a9d6f59 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpProductFragment.kt @@ -130,4 +130,13 @@ class SignUpProductFragment : Fragment(), SignUpViewModel.SignUpNavigator { } } } + + override fun createInitialDialog(title: String?, message: String?) { + if (activity != null) { + DialogBuilder.createFullCustomNotificationDialog(activity, title, + message) { + findNavControllerSafely()?.navigate(net.ivpn.core.R.id.connectFragment) + } + } + } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt b/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt index 511598453..ea8c3c272 100644 --- a/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt +++ b/store/src/main/java/net/ivpn/client/signup/SignUpViewModel.kt @@ -360,13 +360,20 @@ class SignUpViewModel @Inject constructor( override fun onPurchaseStateChanged(state: BillingManagerWrapper.PurchaseState?) { when (state) { - BillingManagerWrapper.PurchaseState.PURCHASE_PENDING -> { + BillingManagerWrapper.PurchaseState.PAYMENT_PENDING -> { navigator?.createDialog( "Pending payment", "Payment is pending for approval. We will complete the transaction as soon as payment is approved." ) } + BillingManagerWrapper.PurchaseState.INITIAL_PAYMENT_PENDING -> { + navigator?.createInitialDialog( + "Pending payment", + "Payment is pending for approval. We will complete the transaction as soon as payment is approved." + ) + } + else -> {} } } @@ -432,5 +439,7 @@ class SignUpViewModel @Inject constructor( fun onGoogleConnectFailure() fun createDialog(title: String?, message: String?) + + fun createInitialDialog(title: String?, message: String?) } } \ No newline at end of file From e69695e692e404fecb4cd4fe90b6c08596854862 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:40:06 +0000 Subject: [PATCH 41/73] build(deps): bump golang.org/x/net in /core/tools/libwg-go Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] --- core/tools/libwg-go/go.mod | 6 +++--- core/tools/libwg-go/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/tools/libwg-go/go.mod b/core/tools/libwg-go/go.mod index 3a311a198..bd91bad61 100644 --- a/core/tools/libwg-go/go.mod +++ b/core/tools/libwg-go/go.mod @@ -3,12 +3,12 @@ module golang.zx2c4.com/wireguard/android go 1.19 require ( - golang.org/x/sys v0.15.0 + golang.org/x/sys v0.18.0 golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 ) require ( - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect ) diff --git a/core/tools/libwg-go/go.sum b/core/tools/libwg-go/go.sum index 6c99c891f..e5f7ff176 100644 --- a/core/tools/libwg-go/go.sum +++ b/core/tools/libwg-go/go.sum @@ -1,9 +1,9 @@ -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU= From fe9ce103bd8dfe24d383801a16ff8c73d68c8a31 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 20 May 2024 14:24:15 +0200 Subject: [PATCH 42/73] build(sdk): update minSdkVersion --- core/build.gradle | 2 +- fdroid/build.gradle | 2 +- liboqs-android/build.gradle | 2 +- site/build.gradle | 2 +- store/build.gradle | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 4df597eee..925074fa2 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -28,7 +28,7 @@ android { compileSdkVersion 33 defaultConfig { - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 33 versionCode 130 versionName "2.10.7" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index d4acc92a5..1a9c711f6 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -29,7 +29,7 @@ android { defaultConfig { applicationId "net.ivpn.client" - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 33 versionCode 130 versionName "2.10.7" diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 0a545d2fd..35f0e9bcb 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -7,7 +7,7 @@ android { compileSdkVersion 33 defaultConfig { - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 33 versionCode 130 versionName "2.10.7" diff --git a/site/build.gradle b/site/build.gradle index 4766f0bfe..453f7e5e8 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -29,7 +29,7 @@ android { defaultConfig { applicationId "net.ivpn.client" - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 33 versionCode 130 versionName "2.10.7" diff --git a/store/build.gradle b/store/build.gradle index 4a7b0a26e..e4637d1d8 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -30,7 +30,7 @@ android { defaultConfig { applicationId "net.ivpn.client" - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 33 versionCode 130 versionName "2.10.7" From 2586211b3fb54509164a6d750fb1f1b1934277ce Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 20 May 2024 14:49:21 +0200 Subject: [PATCH 43/73] build(openvpn): update .gitmodules --- .gitmodules | 2 +- core/src/main/cpp/openvpn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 680bf7275..dfd55314e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://git.zx2c4.com/wireguard-tools [submodule "core/src/main/cpp/openvpn"] path = core/src/main/cpp/openvpn - url = https://github.com/schwabe/openvpn + url = https://github.com/ivpn/android-openvpn [submodule "core/src/main/cpp/openssl"] path = core/src/main/cpp/openssl url = https://github.com/schwabe/platform_external_openssl diff --git a/core/src/main/cpp/openvpn b/core/src/main/cpp/openvpn index b3eb7a46c..4a5465a77 160000 --- a/core/src/main/cpp/openvpn +++ b/core/src/main/cpp/openvpn @@ -1 +1 @@ -Subproject commit b3eb7a46c465696b38debfc2d2c1dff8971c4035 +Subproject commit 4a5465a773d6c636cccd22b182a604a47ab9e073 From 879488c73eb54ac21a5ad2eee5e28ac05649555b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 20 May 2024 19:20:13 +0200 Subject: [PATCH 44/73] feat(build): update liboqs interface --- liboqs-android/jni/jni/KeyEncapsulation.c | 1 - liboqs-android/jni/jni/Rand.c | 21 ---------- liboqs-android/jni/jni/Rand.h | 8 ---- .../src/main/java/net/ivpn/liboqs/Common.java | 38 ++++++++++++++++--- .../src/main/java/net/ivpn/liboqs/KEMs.java | 6 +-- .../src/main/java/net/ivpn/liboqs/Rand.java | 35 ----------------- .../src/main/java/net/ivpn/liboqs/Sigs.java | 6 +-- 7 files changed, 38 insertions(+), 77 deletions(-) diff --git a/liboqs-android/jni/jni/KeyEncapsulation.c b/liboqs-android/jni/jni/KeyEncapsulation.c index a392678bf..3468edef6 100644 --- a/liboqs-android/jni/jni/KeyEncapsulation.c +++ b/liboqs-android/jni/jni/KeyEncapsulation.c @@ -47,7 +47,6 @@ JNIEXPORT jobject JNICALL Java_net_ivpn_liboqs_KeyEncapsulation_get_1KEM_1detail // Call back constructor to allocate a new instance, with an int argument jobject _nativeKED = (*env)->NewObject(env, cls, constructor_meth_id_, obj); - // We need to pass obj (superclass) additionally to run on android: https://stackoverflow.com/questions/25363027/jni-getmethodid-not-working-for-constructor-of-inner-class OQS_KEM *kem = (OQS_KEM *) getHandle(env, obj, "native_kem_handle_"); diff --git a/liboqs-android/jni/jni/Rand.c b/liboqs-android/jni/jni/Rand.c index 874c7024b..8ed2f1076 100644 --- a/liboqs-android/jni/jni/Rand.c +++ b/liboqs-android/jni/jni/Rand.c @@ -41,24 +41,3 @@ JNIEXPORT jint JNICALL Java_net_ivpn_liboqs_Rand_randombytes_1switch_1algorithm_ (*env)->ReleaseStringUTFChars(env, jstr, alg_name_native); return (rv_ == OQS_SUCCESS) ? 0 : -1; } - -/* - * Class: org_openquantumsafe_Rand - * Method: randombytes_nist_kat_init - * Signature: ([B[BJ)V - */ -JNIEXPORT void JNICALL Java_net_ivpn_liboqs_Rand_randombytes_1nist_1kat_1init - (JNIEnv *env, jclass cls, jbyteArray jentropy_input, jbyteArray jpers_str, jlong pers_str_len) -{ - jbyte *entropy_input_native = (*env)->GetByteArrayElements(env, jentropy_input, 0); - - if (pers_str_len == 0) { - OQS_randombytes_nist_kat_init_256bit((uint8_t*) entropy_input_native, NULL); - } else { - jbyte *pers_str_native = (*env)->GetByteArrayElements(env, jpers_str, 0); - OQS_randombytes_nist_kat_init_256bit((uint8_t*) entropy_input_native, (uint8_t*) pers_str_native); - (*env)->ReleaseByteArrayElements(env, jpers_str, pers_str_native, JNI_ABORT); - } - - (*env)->ReleaseByteArrayElements(env, jentropy_input, entropy_input_native, JNI_ABORT); -} diff --git a/liboqs-android/jni/jni/Rand.h b/liboqs-android/jni/jni/Rand.h index e7a98bb03..37010ed4a 100644 --- a/liboqs-android/jni/jni/Rand.h +++ b/liboqs-android/jni/jni/Rand.h @@ -23,14 +23,6 @@ JNIEXPORT jbyteArray JNICALL Java_net_ivpn_liboqs_Rand_randombytes JNIEXPORT jint JNICALL Java_net_ivpn_liboqs_Rand_randombytes_1switch_1algorithm_1native (JNIEnv *, jclass, jstring); -/* - * Class: org_openquantumsafe_Rand - * Method: randombytes_nist_kat_init - * Signature: ([B[BJ)V - */ -JNIEXPORT void JNICALL Java_net_ivpn_liboqs_Rand_randombytes_1nist_1kat_1init - (JNIEnv *, jclass, jbyteArray, jbyteArray, jlong); - #ifdef __cplusplus } #endif diff --git a/liboqs-android/src/main/java/net/ivpn/liboqs/Common.java b/liboqs-android/src/main/java/net/ivpn/liboqs/Common.java index 4ff1b530b..a51bf6f49 100644 --- a/liboqs-android/src/main/java/net/ivpn/liboqs/Common.java +++ b/liboqs-android/src/main/java/net/ivpn/liboqs/Common.java @@ -1,7 +1,10 @@ package net.ivpn.liboqs; -import android.os.Build; - +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; import java.util.Arrays; public class Common { @@ -25,10 +28,33 @@ public static boolean isLinux() { } public static void loadNativeLibrary() { - System.err.println("---------------------------"); - System.err.println("Loading liboqs for: " + Build.CPU_ABI); - System.err.println("---------------------------"); - System.loadLibrary("oqs-jni"); + // If the library is in the java library path, load it directly. (e.g., -Djava.library.path=src/main/resources) + try { + System.loadLibrary("oqs-jni"); + // Otherwise load the library from the liboqs-java.jar + } catch (UnsatisfiedLinkError e) { + String libName = "llliboqs-jni.so"; + if (Common.isLinux()) { + libName = "liboqs-jni.so"; + } else if (Common.isMac()) { + libName = "liboqs-jni.jnilib"; + } else if (Common.isWindows()) { + libName = "oqs-jni.dll"; + } + URL url = KEMs.class.getResource("/" + libName); + File tmpDir; + try { + tmpDir = Files.createTempDirectory("oqs-native-lib").toFile(); + tmpDir.deleteOnExit(); + File nativeLibTmpFile = new File(tmpDir, libName); + nativeLibTmpFile.deleteOnExit(); + InputStream in = url.openStream(); + Files.copy(in, nativeLibTmpFile.toPath()); + System.load(nativeLibTmpFile.getAbsolutePath()); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + } } public static > void print_list(T list) { diff --git a/liboqs-android/src/main/java/net/ivpn/liboqs/KEMs.java b/liboqs-android/src/main/java/net/ivpn/liboqs/KEMs.java index b34d9a9ee..63bff77d2 100644 --- a/liboqs-android/src/main/java/net/ivpn/liboqs/KEMs.java +++ b/liboqs-android/src/main/java/net/ivpn/liboqs/KEMs.java @@ -15,7 +15,7 @@ public class KEMs { /** * The single KEMs class instance. */ - private static KEMs single_instance = null; + private static KEMs single_instance = null; private KEMs() {} @@ -23,9 +23,9 @@ private KEMs() {} * \brief Make sure that at most one instance is generated. * \return Singleton instance */ - public static synchronized KEMs get_instance() { + public static synchronized KEMs get_instance() { if (single_instance == null) { - single_instance = new KEMs(); + single_instance = new KEMs(); } return single_instance; } diff --git a/liboqs-android/src/main/java/net/ivpn/liboqs/Rand.java b/liboqs-android/src/main/java/net/ivpn/liboqs/Rand.java index 2a7a9247d..027996402 100644 --- a/liboqs-android/src/main/java/net/ivpn/liboqs/Rand.java +++ b/liboqs-android/src/main/java/net/ivpn/liboqs/Rand.java @@ -36,39 +36,4 @@ public static void randombytes_switch_algorithm(String alg_name) throw new RuntimeException("Cannot switch rand algorithm"); } } - - /** - * \brief Wrapper for OQS_API void OQS_randombytes_nist_kat_init( - * const uint8_t *entropy_input, - * const uint8_t *personalization_string, - * int security_strength); - * - * \param Entropy input seed, must be exactly 48 bytes long - * \param Entropy seed length - * \param Optional personalization string, which, if non-empty, must be at - * least 48 byte[] long - * \param personalization string length - */ - private static native void randombytes_nist_kat_init(byte[] entropy_input, - byte[] personalization_string, - long personalization_string_len); - - public static void randombytes_nist_kat_init(byte[] entropy_input) { - randombytes_nist_kat_init(entropy_input, null); - } - - public static void randombytes_nist_kat_init(byte[] entropy_input, - byte[] personalization_string) { - if (entropy_input.length != 48) { - throw new RuntimeException("The entropy source must be exactly 48 byte[] long"); - } - if (personalization_string == null) { - randombytes_nist_kat_init(entropy_input, null, 0); - return; - } - if (personalization_string.length < 48) { - throw new RuntimeException("The personalization string must be either empty or at least 48 byte[] long"); - } - randombytes_nist_kat_init(entropy_input, personalization_string, personalization_string.length); - } } diff --git a/liboqs-android/src/main/java/net/ivpn/liboqs/Sigs.java b/liboqs-android/src/main/java/net/ivpn/liboqs/Sigs.java index ed6e31dde..a86a7fd19 100644 --- a/liboqs-android/src/main/java/net/ivpn/liboqs/Sigs.java +++ b/liboqs-android/src/main/java/net/ivpn/liboqs/Sigs.java @@ -15,7 +15,7 @@ public class Sigs { /** * The single Sigs class instance. */ - private static Sigs single_instance = null; + private static Sigs single_instance = null; private Sigs() {} @@ -23,9 +23,9 @@ private Sigs() {} * \brief Make sure that at most one instance is generated. * \return Singleton instance */ - public static synchronized Sigs get_instance() { + public static synchronized Sigs get_instance() { if (single_instance == null) { - single_instance = new Sigs(); + single_instance = new Sigs(); } return single_instance; } From 21d9a106844dda98e1e9fa1cccd936fe64f719d1 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 20 May 2024 19:20:42 +0200 Subject: [PATCH 45/73] feat(build): update liboqs --- liboqs-android/jni/liboqs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liboqs-android/jni/liboqs b/liboqs-android/jni/liboqs index fbb67ae2b..5cc3282a7 160000 --- a/liboqs-android/jni/liboqs +++ b/liboqs-android/jni/liboqs @@ -1 +1 @@ -Subproject commit fbb67ae2bb1c5c9901844145daf43ba85bbee6ce +Subproject commit 5cc3282a744434e924e8b29cb732d14df0d3340a From c1b8407ca0a27c5d55e977aa8cbfd2c414d05797 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 27 May 2024 15:03:06 +0200 Subject: [PATCH 46/73] feat(api): update AddWireGuardPublicKeyRequestBody.java --- .../ivpn/core/rest/data/session/SessionNewRequestBody.java | 5 +++++ .../data/wireguard/AddWireGuardPublicKeyRequestBody.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewRequestBody.java b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewRequestBody.java index 6f60ff377..fde4d167a 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewRequestBody.java +++ b/core/src/main/java/net/ivpn/core/rest/data/session/SessionNewRequestBody.java @@ -36,6 +36,9 @@ public class SessionNewRequestBody { @SerializedName("kem_public_key1") @Expose private String kemPublicKey; + @SerializedName("kem_library_version") + @Expose + private String kemLibraryVersion; @SerializedName("app_name") @Expose private String appName; @@ -56,6 +59,7 @@ public SessionNewRequestBody(String username, String wgPublicKey, String kemPubl this.username = username; this.wgPublicKey = wgPublicKey; this.kemPublicKey = kemPublicKey; + this.kemLibraryVersion = "0.10.0"; this.appName = "IVPN for Android"; this.force = force; } @@ -64,6 +68,7 @@ public SessionNewRequestBody(String username, String wgPublicKey, String kemPubl this.username = username; this.wgPublicKey = wgPublicKey; this.kemPublicKey = kemPublicKey; + this.kemLibraryVersion = "0.10.0"; this.appName = "IVPN for Android"; this.force = force; this.tfaToken = tfaToken; diff --git a/core/src/main/java/net/ivpn/core/rest/data/wireguard/AddWireGuardPublicKeyRequestBody.java b/core/src/main/java/net/ivpn/core/rest/data/wireguard/AddWireGuardPublicKeyRequestBody.java index e187824c8..d3ff3157c 100644 --- a/core/src/main/java/net/ivpn/core/rest/data/wireguard/AddWireGuardPublicKeyRequestBody.java +++ b/core/src/main/java/net/ivpn/core/rest/data/wireguard/AddWireGuardPublicKeyRequestBody.java @@ -39,18 +39,23 @@ public class AddWireGuardPublicKeyRequestBody { @SerializedName("kem_public_key1") @Expose private String kemPublicKey; + @SerializedName("kem_library_version") + @Expose + private String kemLibraryVersion; public AddWireGuardPublicKeyRequestBody(String sessionToken, String publicKey, String connectedPublicKey, String kemPublicKey) { this.sessionToken = sessionToken; this.publicKey = publicKey; this.connectedPublicKey = connectedPublicKey; this.kemPublicKey = kemPublicKey; + this.kemLibraryVersion = "0.10.0"; } public AddWireGuardPublicKeyRequestBody(String sessionToken, String publicKey, String kemPublicKey) { this.sessionToken = sessionToken; this.publicKey = publicKey; this.kemPublicKey = kemPublicKey; + this.kemLibraryVersion = "0.10.0"; } public String getSessionToken() { From 132e39843fb408087fd621d2e7a56b3d6e2d9a3a Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 3 Jun 2024 11:49:31 +0200 Subject: [PATCH 47/73] docs: update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05dc4004d..bc7f86204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## Version 2.10.8 - Unreleased + +[IMPROVED] Post-Quantum library updated to the latest version +[IMPROVED] Support for pending payments +[NOTE] Removed support for Android 7.0 and older + ## Version 2.10.7 - 2024-02-12 [NEW] Device Management From 6e873830c4561725d9f90deb4c2fdfab12c18c01 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 3 Jun 2024 14:57:43 +0200 Subject: [PATCH 48/73] docs: update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7f86204..3e8ae52b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,15 @@ All notable changes to this project will be documented in this file. -## Version 2.10.8 - Unreleased +## Version 2.10.8 - 2024-06-03 [IMPROVED] Post-Quantum library updated to the latest version [IMPROVED] Support for pending payments [NOTE] Removed support for Android 7.0 and older +[Download IVPN Client v2.10.8](https://www.ivpn.net/releases/android/IVPNv2.10.8site.apk) +SHA256: 5f3de49a59b80f06087f440d3e7d939d2f815d7ba944a1a75c90a20e447865cd + ## Version 2.10.7 - 2024-02-12 [NEW] Device Management From 30b049807c18bb406e59a8aefe6269e1a246979b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jul 2024 16:02:29 +0200 Subject: [PATCH 49/73] refactor: remove tests placeholders --- .../java/net/ivpn/core/SecureStorageTest.java | 63 ----- .../ivpn/core/common/ProfileStorageTest.java | 27 -- .../prefs/PreferenceContentGenerator.java | 8 - .../core/common/prefs/PreferenceTest.java | 247 ------------------ .../ivpn/core/common/prefs/SettingsTest.java | 155 ----------- .../untrustedwifi/ItemWifiViewModelTest.java | 42 --- .../UntrustedWifiViewModelTest.java | 91 ------- .../net/ivpn/core/vpn/VPNControllerTest.java | 246 ----------------- .../common/distance/DistanceProviderTest.kt | 53 ---- .../ivpn/client/ExampleInstrumentedTest.kt | 24 -- .../java/net/ivpn/client/ExampleUnitTest.kt | 17 -- .../ivpn/client/ExampleInstrumentedTest.kt | 24 -- .../java/net/ivpn/client/ExampleUnitTest.kt | 17 -- .../net/ivpn/core/ExampleInstrumentedTest.kt | 24 -- .../java/net/ivpn/core/ExampleUnitTest.kt | 17 -- 15 files changed, 1055 deletions(-) delete mode 100644 core/src/androidTest/java/net/ivpn/core/SecureStorageTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/common/ProfileStorageTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceContentGenerator.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/common/prefs/SettingsTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/ItemWifiViewModelTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/UntrustedWifiViewModelTest.java delete mode 100644 core/src/androidTest/java/net/ivpn/core/vpn/VPNControllerTest.java delete mode 100644 core/src/test/java/net/ivpn/core/common/distance/DistanceProviderTest.kt delete mode 100644 fdroid/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt delete mode 100644 fdroid/src/test/java/net/ivpn/client/ExampleUnitTest.kt delete mode 100644 site/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt delete mode 100644 site/src/test/java/net/ivpn/client/ExampleUnitTest.kt delete mode 100644 store/src/androidTest/java/net/ivpn/core/ExampleInstrumentedTest.kt delete mode 100644 store/src/test/java/net/ivpn/core/ExampleUnitTest.kt diff --git a/core/src/androidTest/java/net/ivpn/core/SecureStorageTest.java b/core/src/androidTest/java/net/ivpn/core/SecureStorageTest.java deleted file mode 100644 index 7bf6a1791..000000000 --- a/core/src/androidTest/java/net/ivpn/core/SecureStorageTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.ivpn.core; - -public class SecureStorageTest { - -// private static final String FIELD1 = "FIELD1"; -// private static final String FIELD2 = "FIELD2"; -// -// private static final String FIELD1_VALUE = "FIELD1_VALUE"; -// private static final String FIELD2_VALUE = "FIELD2_VALUE"; -// -// private SecureStorage store; -// private Context context; -// -// @Before -// public void setup() { -// context = InstrumentationRegistry.getTargetContext(); -// store = SecureStorage.INSTANCE; -// } -// -// @Test() -// public void fieldNotExistIfStoreEmpty() throws Exception { -// store.init(context); -// -// boolean results = store.isFieldsExist(FIELD1); -// -// assertFalse(results); -// } -// -// @Test(timeout = 5000) -// public void putAndCheckForExistingTwoDifferentFields() throws InterruptedException { -// store.init(context); -// store.putString(FIELD1, FIELD1_VALUE); -// -// boolean result = store.isFieldsExist(FIELD1, FIELD2); -// -// assertFalse(result); -// } -// -// @Test(timeout = 5000) -// public void putAndGetTwoDifferentFields() throws InterruptedException { -// store.init(context); -// store.putString(FIELD1, FIELD1_VALUE); -// store.putString(FIELD2, FIELD2_VALUE); -// -// boolean result = store.isFieldsExist(FIELD1, FIELD2); -// -// assertTrue(result); -// -// String value1 = store.getString(FIELD1); -// String value2 = store.getString(FIELD2); -// -// assertNotNull(value1); -// assertNotNull(value2); -// -// assertEquals(FIELD1_VALUE, value1); -// assertEquals(FIELD2_VALUE, value2); -// } -// -// @After -// public void release() { -// store.clear(); -// } -} diff --git a/core/src/androidTest/java/net/ivpn/core/common/ProfileStorageTest.java b/core/src/androidTest/java/net/ivpn/core/common/ProfileStorageTest.java deleted file mode 100644 index 68419aba5..000000000 --- a/core/src/androidTest/java/net/ivpn/core/common/ProfileStorageTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.ivpn.core.common; - -import org.junit.Test; -import static org.junit.Assert.*; -import de.blinkt.openvpn.VpnProfile; - -public class ProfileStorageTest { - - final String profileName = "TestVpnProfile"; - - @Test - public void writeAndReadValidProfile() { - VpnProfile profile = new VpnProfile(profileName); - - ProfileStorage.writeProfile(profile); - VpnProfile profileFromStorage = ProfileStorage.readProfile(); - assertEquals(profile, profileFromStorage); - assertEquals(profileName, profileFromStorage.mName); - } - - @Test - public void writeAndReadNullProfile() { - ProfileStorage.writeProfile(null); - VpnProfile profileFromStorage = ProfileStorage.readProfile(); - assertNull(profileFromStorage); - } -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceContentGenerator.java b/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceContentGenerator.java deleted file mode 100644 index 058225c56..000000000 --- a/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceContentGenerator.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.ivpn.core.common.prefs; - -public class PreferenceContentGenerator { - public static String getStubWifiSSID() { - return "IVPN"; - } - -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceTest.java b/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceTest.java deleted file mode 100644 index d4ce8410e..000000000 --- a/core/src/androidTest/java/net/ivpn/core/common/prefs/PreferenceTest.java +++ /dev/null @@ -1,247 +0,0 @@ -package net.ivpn.core.common.prefs; - -import org.junit.After; - -import static org.hamcrest.CoreMatchers.hasItem; - -public class PreferenceTest { - - @After - public void clear() { - Preference.INSTANCE.removeAll(); - } - -// @Test -// public void writeReadLoggingSettings() { -// Preference.INSTANCE.putSettingLogging(false); -// assertFalse(Preference.INSTANCE.getSettingLogging()); -// -// Preference.INSTANCE.putSettingLogging(true); -// assertTrue(Preference.INSTANCE.getSettingLogging()); -// } -// -// @Test -// public void writeReadMultiHopSettings() { -// Preference.INSTANCE.putSettingMultiHop(false); -// assertFalse(Preference.INSTANCE.getSettingMultiHop()); -// -// Preference.INSTANCE.putSettingMultiHop(true); -// assertTrue(Preference.INSTANCE.getSettingMultiHop()); -// } -// -// @Test -// public void writeReadKillSwitchSettings() { -// Preference.INSTANCE.putSettingKillSwitch(false); -// assertFalse(Preference.INSTANCE.getSettingKillSwitch()); -// -// Preference.INSTANCE.putSettingKillSwitch(true); -// assertTrue(Preference.INSTANCE.getSettingKillSwitch()); -// } -// -// @Test -// public void writeReadStartOnBootSettings() { -// Preference.INSTANCE.putSettingStartOnBoot(false); -// assertFalse(Preference.INSTANCE.getSettingStartOnBoot()); -// -// Preference.INSTANCE.putSettingStartOnBoot(true); -// assertTrue(Preference.INSTANCE.getSettingStartOnBoot()); -// } -// -// @Test -// public void writeReadAdvancedKillSwitchSettings() { -// Preference.INSTANCE.putSettingAdvancedKillSwitch(false); -// assertFalse(Preference.INSTANCE.getIsAdvancedKillSwitchDialogEnabled()); -// -// Preference.INSTANCE.putSettingAdvancedKillSwitch(true); -// assertTrue(Preference.INSTANCE.getIsAdvancedKillSwitchDialogEnabled()); -// } -// -// @Test -// public void writeReadNewForPrivateEmailsSettings() { -// Preference.INSTANCE.putIsNewForPrivateEmails(false); -// assertFalse(Preference.INSTANCE.getIsNewForPrivateEmails()); -// -// Preference.INSTANCE.putIsNewForPrivateEmails(true); -// assertTrue(Preference.INSTANCE.getIsNewForPrivateEmails()); -// } -// -// @Test -// public void writeReadPortSettings() { -// Preference.INSTANCE.setPort(77); -// assertEquals(Preference.INSTANCE.getPort(), 77); -// } -// -// @Test -// public void writeReadCurrentServerValid() { -// Server entryServer = new Server(); -// entryServer.setGateway("fr.gw.ivpn.net"); -// -// Server exitServer = new Server(); -// exitServer.setGateway("de.gw.ivpn.net"); -// -// Preference.INSTANCE.setCurrentServer(ServerType.ENTRY, entryServer); -// Preference.INSTANCE.setCurrentServer(ServerType.EXIT, exitServer); -// -// assertEquals(entryServer, Preference.INSTANCE.getCurrentServer(ServerType.ENTRY)); -// assertEquals(exitServer, Preference.INSTANCE.getCurrentServer(ServerType.EXIT)); -// -// //invalid params should be ignored -// Preference.INSTANCE.setCurrentServer(null, entryServer); -// Preference.INSTANCE.setCurrentServer(ServerType.ENTRY, null); -// Preference.INSTANCE.setCurrentServer(ServerType.EXIT, null); -// Preference.INSTANCE.getCurrentServer(null); -// -// assertEquals(entryServer, Preference.INSTANCE.getCurrentServer(ServerType.ENTRY)); -// assertEquals(exitServer, Preference.INSTANCE.getCurrentServer(ServerType.EXIT)); -// } -// -// @Test -// public void writeReadServerList() { -// List list = new ArrayList<>(); -// Server server1 = new Server(); -// server1.setGateway("fr.gw.ivpn.net"); -// -// Server server2 = new Server(); -// server2.setGateway("de.gw.ivpn.net"); -// -// Server server3 = new Server(); -// server3.setGateway("uk.gw.ivpn.net"); -// -// list.add(server1); -// list.add(server2); -// list.add(server3); -// -// Preference.INSTANCE.putServerList(list); -// List listFromPref = Preference.INSTANCE.getServersList(); -// assertNotNull(listFromPref); -// assertEquals(listFromPref.size(), list.size()); -// for (Server server : listFromPref) { -// assertThat(list, hasItem(server)); -// } -// } -// -// @Test -// public void writeReadFavouriteServerList() { -// Server server1 = new Server(); -// server1.setGateway("fr.gw.ivpn.net"); -// -// Server server2 = new Server(); -// server2.setGateway("de.gw.ivpn.net"); -// -// Server server3 = new Server(); -// server3.setGateway("uk.gw.ivpn.net"); -// -// Preference.INSTANCE.addFavouriteServer(server1); -// List favListFromPref = Preference.INSTANCE.getFavouritesServersList(); -// assertNotNull(favListFromPref); -// assertEquals(favListFromPref.size(), 1); -// -// //invalid params and same server should be ignored -// Preference.INSTANCE.addFavouriteServer(server1); -// Preference.INSTANCE.addFavouriteServer(null); -// -// favListFromPref = Preference.INSTANCE.getFavouritesServersList(); -// assertNotNull(favListFromPref); -// assertEquals(favListFromPref.size(), 1); -// -// Preference.INSTANCE.addFavouriteServer(server2); -// Preference.INSTANCE.addFavouriteServer(server3); -// -// favListFromPref = Preference.INSTANCE.getFavouritesServersList(); -// assertNotNull(favListFromPref); -// assertEquals(favListFromPref.size(), 3); -// assertThat(favListFromPref, hasItem(server1)); -// assertThat(favListFromPref, hasItem(server2)); -// assertThat(favListFromPref, hasItem(server3)); -// -// Preference.INSTANCE.removeFavouriteServer(server1); -// Preference.INSTANCE.removeFavouriteServer(server2); -// favListFromPref = Preference.INSTANCE.getFavouritesServersList(); -// assertNotNull(favListFromPref); -// assertEquals(favListFromPref.size(), 1); -// assertThat(favListFromPref, hasItem(server3)); -// -// //invalid params and same server should be ignored -// Preference.INSTANCE.removeFavouriteServer(null); -// Preference.INSTANCE.removeFavouriteServer(server1); -// assertNotNull(favListFromPref); -// assertEquals(favListFromPref.size(), 1); -// assertThat(favListFromPref, hasItem(server3)); -// } -// -// @Test -// public void allowDisallowApps() { -// Set disallowedApps = new HashSet<>(); -// disallowedApps.add("com.ninegag.android.app"); -// disallowedApps.add("com.google.android.gm"); -// disallowedApps.add("com.facebook.katana"); -// -// Preference.INSTANCE.disallowAllPackages(disallowedApps); -// Set disallowedAppsFromPref = Preference.INSTANCE.getDisallowedPackages(); -// assertNotNull(disallowedAppsFromPref); -// assertEquals(disallowedAppsFromPref.size(), disallowedApps.size()); -// for (String packageName : disallowedApps) { -// assertThat(disallowedAppsFromPref, hasItem(packageName)); -// } -// -// //invalid params should be ignored -// Preference.INSTANCE.allowPackage("com.google.android.youtube"); -// Preference.INSTANCE.allowPackage("com.snapchat.android"); -// Preference.INSTANCE.allowPackage(null); -// -// disallowedAppsFromPref = Preference.INSTANCE.getDisallowedPackages(); -// assertNotNull(disallowedAppsFromPref); -// assertEquals(disallowedAppsFromPref.size(), disallowedApps.size()); -// for (String packageName : disallowedApps) { -// assertThat(disallowedAppsFromPref, hasItem(packageName)); -// } -// -// Preference.INSTANCE.allowAllPackages(); -// disallowedAppsFromPref = Preference.INSTANCE.getDisallowedPackages(); -// assertNotNull(disallowedAppsFromPref); -// assertEquals(disallowedAppsFromPref.size(), 0); -// -// Preference.INSTANCE.disallowPackage(null); -// Preference.INSTANCE.disallowPackage("com.google.android.youtube"); -// Preference.INSTANCE.disallowPackage("com.snapchat.android"); -// disallowedAppsFromPref = Preference.INSTANCE.getDisallowedPackages(); -// assertNotNull(disallowedAppsFromPref); -// assertEquals(disallowedAppsFromPref.size(), 2); -// } -// -// @Test -// public void shouldReturnCorrectDefaultUntrustedWifiSetting() { -// assertFalse(Preference.INSTANCE.getSettingNetworkRules()); -// } -// -// @Test -// public void shouldReturnUntrustedWifiSetting() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// assertTrue(Preference.INSTANCE.getSettingNetworkRules()); -// } -// -// @Test -// public void shouldSaveWifiSSID() { -// String wifiSSID = PreferenceContentGenerator.getStubWifiSSID(); -// Preference.INSTANCE.markWifiAsTrusted(wifiSSID); -// Set trustedWifiSSID = Preference.INSTANCE.getTrustedWifiList(); -// assertThat(trustedWifiSSID, hasItem(wifiSSID)); -// } -// -// @Test -// public void shouldIgnoreInvalidWifiSSID() { -// Preference.INSTANCE.markWifiAsTrusted(null); -// Set trustedWifiSSID = Preference.INSTANCE.getTrustedWifiList(); -// assertNotNull(trustedWifiSSID); -// assertTrue(trustedWifiSSID.isEmpty()); -// } -// -// @Test -// public void shouldRemoveWifiSSID() { -// String wifiSSID = PreferenceContentGenerator.getStubWifiSSID(); -// Preference.INSTANCE.markWifiAsTrusted(wifiSSID); -// Preference.INSTANCE.removeMarkWifiAsTrusted(wifiSSID); -// Set trustedWifiSSID = Preference.INSTANCE.getTrustedWifiList(); -// assertTrue(trustedWifiSSID.isEmpty()); -// } -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/common/prefs/SettingsTest.java b/core/src/androidTest/java/net/ivpn/core/common/prefs/SettingsTest.java deleted file mode 100644 index 1b2a47c80..000000000 --- a/core/src/androidTest/java/net/ivpn/core/common/prefs/SettingsTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package net.ivpn.core.common.prefs; - -import androidx.test.filters.LargeTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -@RunWith(AndroidJUnit4.class) -@LargeTest -public class SettingsTest { - - private static final String STANDARD_DNS = "1.1.1.1"; - private static final String STANDARD_DNS_MULTI_HOP = "2.2.2.2"; - private static final String HARDCORE_DNS = "3.3.3.3"; - private static final String HARDCORE_DNS_MULTI_HOP = "4.4.4.4"; - private static final String CUSTOM_DNS = "5.5.5.5"; - - @Before - public void setUp() { - initSettings(); - } - - @Test - public void getDNS1() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(true); - Settings.INSTANCE.enableCustomDNS(true); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, HARDCORE_DNS_MULTI_HOP); - } - - @Test - public void getDNS2() { - Settings.INSTANCE.enableAntiSurveillance(false); - Settings.INSTANCE.enableAntiSurveillanceHardcore(true); - Settings.INSTANCE.enableCustomDNS(true); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, CUSTOM_DNS); - } - - @Test - public void getDNS3() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(true); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, STANDARD_DNS_MULTI_HOP); - } - - @Test - public void getDNS4() { - Settings.INSTANCE.enableAntiSurveillance(false); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(true); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, CUSTOM_DNS); - } - - @Test - public void getDNS5() { - Settings.INSTANCE.enableAntiSurveillance(false); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, null); - } - - @Test - public void getDNS6() { - Settings.INSTANCE.enableAntiSurveillance(false); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(false); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, null); - } - - @Test - public void getDNS7() { - Settings.INSTANCE.enableAntiSurveillance(false); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(true); - Settings.INSTANCE.enableMultiHop(false); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, CUSTOM_DNS); - } - - @Test - public void getDNS8() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(true); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, HARDCORE_DNS_MULTI_HOP); - } - - @Test - public void getDNS9() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(true); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(false); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, HARDCORE_DNS); - } - - @Test - public void getDNS10() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(false); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, STANDARD_DNS); - } - - @Test - public void getDNS11() { - Settings.INSTANCE.enableAntiSurveillance(true); - Settings.INSTANCE.enableAntiSurveillanceHardcore(false); - Settings.INSTANCE.enableCustomDNS(false); - Settings.INSTANCE.enableMultiHop(true); - - String dns = Settings.INSTANCE.getDNS(); - assertSame(dns, STANDARD_DNS_MULTI_HOP); - } - - private void initSettings() { - Settings.INSTANCE.setAntiTrackerDefaultDNS(STANDARD_DNS); - Settings.INSTANCE.setAntiTrackerDefaultDNSMulti(STANDARD_DNS_MULTI_HOP); - Settings.INSTANCE.setAntiTrackerHardcoreDNS(HARDCORE_DNS); - Settings.INSTANCE.setAntiTrackerHardcoreDNSMulti(HARDCORE_DNS_MULTI_HOP); - Settings.INSTANCE.setCustomDNSValue(CUSTOM_DNS); - } -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/ItemWifiViewModelTest.java b/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/ItemWifiViewModelTest.java deleted file mode 100644 index 26ace51e9..000000000 --- a/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/ItemWifiViewModelTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.ivpn.core.ui.untrustedwifi; - -import net.ivpn.core.common.prefs.Preference; - -import org.junit.After; - -import static org.hamcrest.CoreMatchers.hasItem; - -public class ItemWifiViewModelTest { - - private final String wifiSsid = "Wifi1"; - - @After - public void release() { - Preference.INSTANCE.removeAll(); - } - -// @Test -// public void shouldSaveAsTrustedInPrefs() { -// WifiItem item = new WifiItem(wifiSsid, false); -// ItemWifiViewModel viewModel = new ItemWifiViewModel(item); -// -// viewModel.onItemClick(); -// assertTrue(viewModel.isChecked()); -// -// Set trustedWifiList = Preference.INSTANCE.getTrustedWifiList(); -// assertThat(trustedWifiList, hasItem(item.getSsid())); -// } -// -// @Test -// public void shouldRemoveFromTrustedInPrefs() { -// Preference.INSTANCE.markWifiAsTrusted(wifiSsid); -// WifiItem item = new WifiItem(wifiSsid, true); -// ItemWifiViewModel viewModel = new ItemWifiViewModel(item); -// -// viewModel.onItemClick(); -// assertFalse(viewModel.isChecked()); -// -// Set trustedWifiList = Preference.INSTANCE.getTrustedWifiList(); -// assertFalse(trustedWifiList.contains(wifiSsid)); -// } -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/UntrustedWifiViewModelTest.java b/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/UntrustedWifiViewModelTest.java deleted file mode 100644 index d63788cad..000000000 --- a/core/src/androidTest/java/net/ivpn/core/ui/untrustedwifi/UntrustedWifiViewModelTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.ivpn.core.ui.untrustedwifi; - -public class UntrustedWifiViewModelTest { - -// private static final String wifiSsid1 = "Wifi C"; -// private static final String wifiSsid2 = "Wifi A"; -// private static final String wifiSsid3 = "Wifi B"; -// -// @Rule -// public ActivityTestRule activityTestRule -// = new ActivityTestRule<>(WifiActivity.class); -// -// @After -// public void release() { -// Preference.INSTANCE.removeAll(); -// } -// -// @Test -// public void shouldSettingApply() { -// activityTestRule.launchActivity(new Intent()); -// onView(withId(R.id.wifi_main_switcher)).check(matches(isDisplayed())).perform(click()); -// assertTrue(Preference.INSTANCE.getSettingNetworkRules()); -// } -// -// @Test -// public void shouldCommonSwitcherEnabled() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// activityTestRule.launchActivity(new Intent()); -// onView(withId(R.id.wifi_main_switcher)).check(matches(isChecked())); -// } -// -// @Test -// public void shouldSettingsApplyDefaultsCorrect() { -// WifiViewModel viewModel = new WifiViewModel(getWifiManager()); -// assertEquals(viewModel.isUntrustedWifiEnabled.get(), Preference.INSTANCE.getSettingNetworkRules()); -// } -// -// @Test -// public void shouldSettingsApplyCorrect() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// WifiViewModel viewModel = new WifiViewModel(getWifiManager()); -// assertEquals(viewModel.isUntrustedWifiEnabled.get(), Preference.INSTANCE.getSettingNetworkRules()); -// } -// -// @Test -// public void shouldBeSortedByTitles() { -// WifiViewModel viewModel = new WifiViewModel(getWifiManager()); -// List itemList = new ArrayList<>(viewModel.wifiItemList); -// Collections.sort(itemList, new Comparator() { -// @Override -// public int compare(WifiItem item1, WifiItem item2) { -// return item1.getTitle().compareToIgnoreCase(item2.getTitle()); -// } -// }); -// assertArrayEquals(itemList.toArray(), viewModel.wifiItemList.toArray()); -// } -// -// @Test -// public void shouldBeMarkedAsTrusted() { -// Preference.INSTANCE.markWifiAsTrusted(wifiSsid2); -// WifiViewModel viewModel = new WifiViewModel(getWifiManager()); -// for (WifiItem item : viewModel.wifiItemList) { -// if (item.getSsid().equals(wifiSsid2)) { -// assertTrue(item.isTrusted()); -// } else { -// assertFalse(item.isTrusted()); -// } -// } -// } -// -// private WifiManager getWifiManager() { -// List wifiConfigurationList = new ArrayList<>(); -// WifiConfiguration wifi1 = mock(WifiConfiguration.class); -// wifi1.SSID = wifiSsid1; -// -// WifiConfiguration wifi2 = mock(WifiConfiguration.class); -// wifi2.SSID = wifiSsid2; -// -// WifiConfiguration wifi3 = mock(WifiConfiguration.class); -// wifi3.SSID = wifiSsid3; -// -// wifiConfigurationList.add(wifi1); -// wifiConfigurationList.add(wifi2); -// wifiConfigurationList.add(wifi3); -// -// WifiManager wifiManager = mock(WifiManager.class); -// when(wifiManager.getConfiguredNetworks()).thenReturn(wifiConfigurationList); -// -// return wifiManager; -// } -} \ No newline at end of file diff --git a/core/src/androidTest/java/net/ivpn/core/vpn/VPNControllerTest.java b/core/src/androidTest/java/net/ivpn/core/vpn/VPNControllerTest.java deleted file mode 100644 index 9e6489d80..000000000 --- a/core/src/androidTest/java/net/ivpn/core/vpn/VPNControllerTest.java +++ /dev/null @@ -1,246 +0,0 @@ -package net.ivpn.core.vpn; - -import org.junit.Before; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class VPNControllerTest { - - private static final String TAG = VPNControllerTest.class.getSimpleName(); - - private final String connected = "CONNECTED"; - private final String disconnected = "DISCONNECTED"; - private final String msg = ""; - - - @Before - public void init() { -// Intents.init(); -// // Block any intent -// Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor((IntentFilter) null, null, true); -// InstrumentationRegistry.getInstrumentation().addMonitor(monitor); - - } - -// @After -// public void release() { -// Intents.release(); -// Preference.INSTANCE.removeAll(); -// GlobalBehaviorController.INSTANCE.release(); -// VpnStatus.updateStateString(disconnected, msg); -// } -// -// @Test -// public void shouldBeNoneAppState() { -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(VPNState.NONE, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldBeVpnAppState() { -// VpnStatus.updateStateString(connected, msg); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(VPNState.VPN, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldBeGuardAppState() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldBeBothAppState() { -// VpnStatus.updateStateString(connected, msg); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldBeNoneGuardState() { -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(GuardState.NONE, GlobalBehaviorController.INSTANCE.getGuardState()); -// } -// -// @Test -// public void shouldBeKillSwitchGuardState() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(GuardState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getGuardState()); -// } -// -// @Test -// public void shouldBeWifiWatcherGuardState() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(GuardState.WIFI_WATCHER, GlobalBehaviorController.INSTANCE.getGuardState()); -// } -// -// @Test -// public void shouldBeBothGuardState() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// } -// -// @Test -// public void shouldEnableKillSwitch() { -// GlobalBehaviorController.INSTANCE.init(); -// assertFalse(GlobalBehaviorController.INSTANCE.isKillSwitchShouldBeStarted()); -// } -// -// @Test -// public void shouldEnableKillSwitch2() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// GlobalBehaviorController.INSTANCE.init(); -// assertTrue(GlobalBehaviorController.INSTANCE.isKillSwitchShouldBeStarted()); -// } -// -// @Test -// public void shouldApplyKillSwitchSetting() { -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableKillSwitch(); -// assertEquals(GuardState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldApplyKillSwitchSetting2() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// VpnStatus.updateStateString(connected, msg); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableKillSwitch(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldApplyKillSwitchSetting3() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableKillSwitch(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableKillSwitch() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableKillSwitch(); -// assertEquals(GuardState.NONE, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.NONE, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableKillSwitch2() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableKillSwitch(); -// assertEquals(GuardState.WIFI_WATCHER, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableKillSwitch3() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// VpnStatus.updateStateString(connected, msg); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableKillSwitch(); -// assertEquals(GuardState.WIFI_WATCHER, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldApplyWifiWatcherSetting() { -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableWifiWatcher(); -// assertEquals(GuardState.WIFI_WATCHER, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldApplyWifiWatcherSetting2() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableWifiWatcher(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldApplyWifiWatcherSetting3() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// VpnStatus.updateStateString(connected, msg); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.enableWifiWatcher(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableWifiWatcher() { -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableWifiWatcher(); -// assertEquals(GuardState.NONE, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.NONE, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableWifiWatcher2() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableWifiWatcher(); -// assertEquals(GuardState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldDisableWifiWatcher3() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// VpnStatus.updateStateString(connected, msg); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.disableWifiWatcher(); -// assertEquals(GuardState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldStartVpn() { -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.startVPN(); -//// intended(hasComponent(new ComponentName(IVPNApplication.getApplication(), IVPNService.class))); -//// intended(toPackage("net.ivpn.client")); -// assertEquals(GuardState.NONE, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.VPN, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldStartVpn2() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.startVPN(); -// assertEquals(GuardState.KILL_SWITCH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -// -// @Test -// public void shouldStartVpn3() { -// Preference.INSTANCE.putSettingKillSwitch(true); -// Preference.INSTANCE.putSettingsNetworkRules(true); -// GlobalBehaviorController.INSTANCE.init(); -// GlobalBehaviorController.INSTANCE.startVPN(); -// assertEquals(GuardState.BOTH, GlobalBehaviorController.INSTANCE.getGuardState()); -// assertEquals(VPNState.BOTH, GlobalBehaviorController.INSTANCE.getState()); -// } -} \ No newline at end of file diff --git a/core/src/test/java/net/ivpn/core/common/distance/DistanceProviderTest.kt b/core/src/test/java/net/ivpn/core/common/distance/DistanceProviderTest.kt deleted file mode 100644 index 7f6db3dc0..000000000 --- a/core/src/test/java/net/ivpn/core/common/distance/DistanceProviderTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package net.ivpn.core.common.distance - -import org.junit.Assert.* -import org.junit.Test - -class DistanceProviderTest { - - - companion object { - const val DISTANCE_DELTA = 1.0f - } - - @Test - fun testCorrectResult() { - val parisCoordinates = Pair(48.85341f, 2.3488f) - val kyivCoordinates = Pair(50.450001f, 30.523333f) - - val correctDistance = 2023.71f - - assertEquals( - correctDistance, - DistanceProvider.getDistanceBetween(parisCoordinates, kyivCoordinates), - DISTANCE_DELTA - ) - } - - @Test - fun testCorrectEdgeCase() { - val somePointCoordinates = Pair(-90.0f, 180.0f) - val kyivCoordinates = Pair(50.450001f, 30.523333f) - - val correctDistance = 15616.58f - - assertEquals( - DistanceProvider.getDistanceBetween(somePointCoordinates, kyivCoordinates), - correctDistance, - DISTANCE_DELTA - ) - } - - @Test - fun testSameCoordinateCase() { - val kyivCoordinates = Pair(50.450001f, 30.523333f) - - val correctDistance = 0.0f - - assertEquals( - DistanceProvider.getDistanceBetween(kyivCoordinates, kyivCoordinates), - correctDistance, - DISTANCE_DELTA - ) - } -} \ No newline at end of file diff --git a/fdroid/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt b/fdroid/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt deleted file mode 100644 index 4b09f3860..000000000 --- a/fdroid/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.ivpn.client - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("net.ivpn.client", appContext.packageName) - } -} \ No newline at end of file diff --git a/fdroid/src/test/java/net/ivpn/client/ExampleUnitTest.kt b/fdroid/src/test/java/net/ivpn/client/ExampleUnitTest.kt deleted file mode 100644 index 0ef243427..000000000 --- a/fdroid/src/test/java/net/ivpn/client/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.ivpn.client - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/site/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt b/site/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt deleted file mode 100644 index 4b09f3860..000000000 --- a/site/src/androidTest/java/net/ivpn/client/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.ivpn.client - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("net.ivpn.client", appContext.packageName) - } -} \ No newline at end of file diff --git a/site/src/test/java/net/ivpn/client/ExampleUnitTest.kt b/site/src/test/java/net/ivpn/client/ExampleUnitTest.kt deleted file mode 100644 index 0ef243427..000000000 --- a/site/src/test/java/net/ivpn/client/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.ivpn.client - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/store/src/androidTest/java/net/ivpn/core/ExampleInstrumentedTest.kt b/store/src/androidTest/java/net/ivpn/core/ExampleInstrumentedTest.kt deleted file mode 100644 index 8334ad41f..000000000 --- a/store/src/androidTest/java/net/ivpn/core/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.ivpn.core - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("net.ivpn.client", appContext.packageName) - } -} \ No newline at end of file diff --git a/store/src/test/java/net/ivpn/core/ExampleUnitTest.kt b/store/src/test/java/net/ivpn/core/ExampleUnitTest.kt deleted file mode 100644 index fe0dbe676..000000000 --- a/store/src/test/java/net/ivpn/core/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.ivpn.core - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file From 32b4d01a45fae1d3ceb1a19f342a27b9318aa0b4 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jul 2024 16:19:23 +0200 Subject: [PATCH 50/73] refactor: update MapView.kt --- core/src/main/java/net/ivpn/core/v2/map/MapView.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/v2/map/MapView.kt b/core/src/main/java/net/ivpn/core/v2/map/MapView.kt index 59493e8e0..3ae9fafe4 100644 --- a/core/src/main/java/net/ivpn/core/v2/map/MapView.kt +++ b/core/src/main/java/net/ivpn/core/v2/map/MapView.kt @@ -96,7 +96,7 @@ class MapView @JvmOverloads constructor( } override fun onScroll( - e1: MotionEvent, + e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float @@ -109,8 +109,10 @@ class MapView @JvmOverloads constructor( } override fun onFling( - e1: MotionEvent, e2: MotionEvent, - velocityX: Float, velocityY: Float + e1: MotionEvent?, + e2: MotionEvent, + velocityX: Float, + velocityY: Float ): Boolean { fling((-velocityX).toInt(), (-velocityY).toInt()) return true From b54af830d4057e70ff105979130e46511a6af0ad Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jul 2024 17:31:01 +0200 Subject: [PATCH 51/73] build: update build.gradle --- core/build.gradle | 6 +++--- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 6 +++--- store/build.gradle | 10 +++++----- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index b10d3e808..6a793fa3b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -26,10 +26,10 @@ android { } } - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 131 versionName "2.10.8" ndkVersion "25.1.8937393" @@ -279,7 +279,7 @@ dependencies { implementation project(path: ':liboqs-android') // For crash logging. - implementation 'io.sentry:sentry-android:4.3.0' + implementation 'io.sentry:sentry-android:6.13.1' implementation "androidx.multidex:multidex:2.0.1" } diff --git a/fdroid/build.gradle b/fdroid/build.gradle index cf284c5ae..f2851435c 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -25,12 +25,12 @@ android { } } - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { applicationId "net.ivpn.client" minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 131 versionName "2.10.8" ndkVersion "25.1.8937393" diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 6ce3bf91a..ba40fc0a7 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -5,10 +5,10 @@ plugins { android { namespace "net.ivpn.liboqs" - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 131 versionName "2.10.8" ndkVersion "25.1.8937393" diff --git a/site/build.gradle b/site/build.gradle index 2763e588d..9031a2601 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -25,12 +25,12 @@ android { } } - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { applicationId "net.ivpn.client" minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 131 versionName "2.10.8" ndkVersion "25.1.8937393" @@ -115,7 +115,7 @@ dependencies { implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" // For crash logging. - implementation 'io.sentry:sentry-android:4.3.0' + implementation 'io.sentry:sentry-android:6.13.1' implementation "androidx.multidex:multidex:2.0.1" diff --git a/store/build.gradle b/store/build.gradle index b61d23528..5201699e1 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -26,12 +26,12 @@ android { } } - compileSdkVersion 33 + compileSdkVersion 34 defaultConfig { applicationId "net.ivpn.client" minSdkVersion 23 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 131 versionName "2.10.8" ndkVersion "25.1.8937393" @@ -97,7 +97,7 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.6.2' // Purchases - implementation 'com.android.billingclient:billing:6.0.0' + implementation 'com.android.billingclient:billing:6.1.0' // Dagger kapt "com.google.dagger:dagger-compiler:$dagger_version" @@ -119,9 +119,9 @@ dependencies { implementation "androidx.multidex:multidex:2.0.1" // For crash logging. - implementation 'io.sentry:sentry-android:4.3.0' + implementation 'io.sentry:sentry-android:6.13.1' testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } \ No newline at end of file From 0ecc1f55cc3f6d10a66b61475b8462a4e4f289b4 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 16 Jul 2024 18:00:37 +0200 Subject: [PATCH 52/73] refactor: update AndroidManifest.xml --- core/src/main/AndroidManifest.xml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 34fdb9a39..5ea2e096c 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -27,6 +27,9 @@ + + + - + android:permission="android.permission.BIND_VPN_SERVICE" + android:foregroundServiceType="specialUse" /> + + android:permission="android.permission.BIND_VPN_SERVICE" + android:foregroundServiceType="specialUse" /> + android:exported="false" + android:foregroundServiceType="specialUse" /> Date: Wed, 17 Jul 2024 11:28:55 +0200 Subject: [PATCH 53/73] chore: update app version and build number --- core/build.gradle | 4 ++-- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 4 ++-- store/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 6a793fa3b..5088ad651 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,8 +30,8 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 131 - versionName "2.10.8" + versionCode 132 + versionName "2.10.9" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index f2851435c..2f22adb75 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 131 - versionName "2.10.8" + versionCode 132 + versionName "2.10.9" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index ba40fc0a7..2e078a89d 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 131 - versionName "2.10.8" + versionCode 132 + versionName "2.10.9" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/site/build.gradle b/site/build.gradle index 9031a2601..4903c0f3c 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 131 - versionName "2.10.8" + versionCode 132 + versionName "2.10.9" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] diff --git a/store/build.gradle b/store/build.gradle index 5201699e1..97b5b7830 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,8 +32,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 131 - versionName "2.10.8" + versionCode 132 + versionName "2.10.9" ndkVersion "25.1.8937393" manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] From fcd8630c1d25024540e9f6b28e116f096a54ed7d Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 22 Jul 2024 14:10:08 +0200 Subject: [PATCH 54/73] fix: update LoginFragment.kt --- .../main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt | 1 + core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt | 6 ++++++ core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt | 2 ++ core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt | 1 + 4 files changed, 10 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt index b6f2d9588..35e3dc791 100644 --- a/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/captcha/CaptchaFragment.kt @@ -155,6 +155,7 @@ class CaptchaFragment : Fragment(), LoginNavigator { } override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { + viewModel.sessionError = error setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt index 7ed36a252..9fcc772c0 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginFragment.kt @@ -41,6 +41,7 @@ import net.ivpn.core.IVPNApplication import net.ivpn.core.R import net.ivpn.core.common.billing.addfunds.Plan import net.ivpn.core.common.extension.findNavControllerSafely +import net.ivpn.core.common.extension.getNavigationResultBoolean import net.ivpn.core.common.extension.navigate import net.ivpn.core.databinding.FragmentLoginBinding import net.ivpn.core.rest.data.session.SessionErrorResponse @@ -154,6 +155,11 @@ class LoginFragment : Fragment(), LoginNavigator, binding.contentLayout.qrCode.setOnClickListener { openQRScanner() } + getNavigationResultBoolean("session_limit_dialogue")?.observe(viewLifecycleOwner) { + if (it) { + viewModel.sessionError?.let { it1 -> openSessionLimitReachedDialogue(it1) } + } + } } private fun initToolbar() { diff --git a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt index 6d43b3b3d..e9b88cf4f 100644 --- a/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/login/LoginViewModel.kt @@ -76,6 +76,8 @@ class LoginViewModel @Inject constructor( var pendingCaptcha: String? = null var pending2FAToken: String? = null + var sessionError: SessionErrorResponse? = null + var tfaFocusListener = View.OnFocusChangeListener { _, hasFocus -> if (hasFocus) { tfaInputState.get()?.let { diff --git a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt index 03acdd942..1f32e7a64 100644 --- a/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt +++ b/core/src/main/java/net/ivpn/core/v2/tfa/TFAFragment.kt @@ -165,6 +165,7 @@ class TFAFragment : Fragment(), LoginNavigator { } override fun openSessionLimitReachedDialogue(error: SessionErrorResponse) { + viewModel.sessionError = error setNavigationResultBoolean(true, "session_limit_dialogue") findNavController().popBackStack() } From d3b28d8ad25151874d9909609ab78a3e0028238d Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 7 Aug 2024 18:22:38 +0200 Subject: [PATCH 55/73] refactor: update build.gradle --- build.gradle | 2 +- core/build.gradle | 2 +- fdroid/build.gradle | 2 +- liboqs-android/build.gradle | 2 +- site/build.gradle | 2 +- store/build.gradle | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index bb3aad305..7bb4746df 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { ext.kotlin_version = '1.8.0' ext.kotlin_coroutines_version = '1.2.1' - ext.nav_version = '2.5.0' + ext.nav_version = '2.5.3' ext.compose_version = '1.4.1' ext.dagger_version = '2.44' repositories { diff --git a/core/build.gradle b/core/build.gradle index 5088ad651..8c8e8e953 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,7 +30,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 132 + versionCode 133 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 2f22adb75..236846c7e 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,7 +31,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 132 + versionCode 133 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 2e078a89d..89ed40a89 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,7 +9,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 132 + versionCode 133 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/site/build.gradle b/site/build.gradle index 4903c0f3c..11ffc0d18 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,7 +31,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 132 + versionCode 133 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/store/build.gradle b/store/build.gradle index 97b5b7830..be941a79b 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,7 +32,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 132 + versionCode 133 versionName "2.10.9" ndkVersion "25.1.8937393" From bdcf0cf8189ffaa0eef7b7b51babb0d2544d2b2b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 8 Aug 2024 17:32:18 +0200 Subject: [PATCH 56/73] docs: update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e8ae52b9..9555509b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. +## Version 2.10.9 - 2024-08-08 + +[IMPROVED] Target Android API level 34 +[FIXED] 2FA login not working when session limit is reached + +[Download IVPN Client v2.10.9](https://www.ivpn.net/releases/android/IVPNv2.10.9site.apk) +SHA256: cd68f954ec349277bec818988c57494a7f64f4447d0c5804607c95977a1b1db2 + ## Version 2.10.8 - 2024-06-03 [IMPROVED] Post-Quantum library updated to the latest version From 75169aedad2519b37f5451ada14505179398fdd5 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 9 Aug 2024 11:47:51 +0200 Subject: [PATCH 57/73] chore: update build.gradle --- core/build.gradle | 2 +- fdroid/build.gradle | 2 +- liboqs-android/build.gradle | 2 +- site/build.gradle | 2 +- store/build.gradle | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 8c8e8e953..8cfb221fb 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,7 +30,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 133 + versionCode 134 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 236846c7e..3511e6c95 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,7 +31,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 133 + versionCode 134 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 89ed40a89..1e7d6d3b7 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,7 +9,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 133 + versionCode 134 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/site/build.gradle b/site/build.gradle index 11ffc0d18..d457c7c4a 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,7 +31,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 133 + versionCode 134 versionName "2.10.9" ndkVersion "25.1.8937393" diff --git a/store/build.gradle b/store/build.gradle index be941a79b..c277694df 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,7 +32,7 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 133 + versionCode 134 versionName "2.10.9" ndkVersion "25.1.8937393" From f489a17b7fb9db4d23717b04a03a7a60caa4711b Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 07:29:43 +0200 Subject: [PATCH 58/73] feat: update strings.xml --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5ed3eb741..1ddad1233 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -186,7 +186,7 @@ Retry - Split tunnelling allows you to control which apps use the VPN tunnel. New apps that you install will automatically use the VPN tunnel. + Split tunnelling allows you to control which apps use the VPN tunnel. New apps that you install will automatically use the VPN tunnel. Only apps with internet permission are listed. TURN ON ALL TURN OFF ALL Show system apps From 67e8d0a150ea17fb13638fd192ebf7c6fdb14486 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 12:03:06 +0200 Subject: [PATCH 59/73] docs: update README.md --- ACKNOWLEDGEMENTS.md | 25 ------------------------- README.md | 1 - 2 files changed, 26 deletions(-) diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index 4ea162b78..530fcbadb 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -1054,31 +1054,6 @@ THE SOFTWARE. limitations under the License. -## sentry-android - -MIT License - -Copyright (c) 2019 Sentry -Copyright (c) 2015 Salomon BRYS for Android ANRWatchDog - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ## slf4j diff --git a/README.md b/README.md index d9ec121ed..77fb03812 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,6 @@ Project dependencies: * [retrofit2](https://github.com/square/retrofit) * [gson](https://github.com/google/gson) * [streamsupport](https://github.com/streamsupport/streamsupport) -* [sentry-android](https://github.com/getsentry/sentry-java) * [slf4j](https://github.com/qos-ch/slf4j) * [logback-android](https://github.com/tony19/logback-android) * [mockito](https://github.com/mockito/mockito) From 582f2daf48040e47d7aee97544d00eae42193ce2 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 12:12:12 +0200 Subject: [PATCH 60/73] feat: update build.gradle --- core/build.gradle | 2 -- fakekeystore.properties | 2 -- fdroid/build.gradle | 1 - site/build.gradle | 4 ---- store/build.gradle | 4 ---- 5 files changed, 13 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 8cfb221fb..fc2c11db7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -278,8 +278,6 @@ dependencies { // liboqs implementation project(path: ':liboqs-android') - // For crash logging. - implementation 'io.sentry:sentry-android:6.13.1' implementation "androidx.multidex:multidex:2.0.1" } diff --git a/fakekeystore.properties b/fakekeystore.properties index 9ead4d06f..3a4f5d300 100644 --- a/fakekeystore.properties +++ b/fakekeystore.properties @@ -1,5 +1,3 @@ -sentry.dsn= - release.store.file='' release.key.alias='' release.key.password='' diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 3511e6c95..53f2b62f2 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -35,7 +35,6 @@ android { versionName "2.10.9" ndkVersion "25.1.8937393" - manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] multiDexEnabled true } diff --git a/site/build.gradle b/site/build.gradle index d457c7c4a..f880b8d1f 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -35,7 +35,6 @@ android { versionName "2.10.9" ndkVersion "25.1.8937393" - manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] multiDexEnabled true @@ -114,9 +113,6 @@ dependencies { // Navigation component dynamic feature module support implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" - // For crash logging. - implementation 'io.sentry:sentry-android:6.13.1' - implementation "androidx.multidex:multidex:2.0.1" testImplementation 'junit:junit:4.+' diff --git a/store/build.gradle b/store/build.gradle index c277694df..a1f748134 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -36,7 +36,6 @@ android { versionName "2.10.9" ndkVersion "25.1.8937393" - manifestPlaceholders = [SENTRY_DSN: keystoreProperties['sentry.dsn']] buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] multiDexEnabled true } @@ -118,9 +117,6 @@ dependencies { implementation "androidx.multidex:multidex:2.0.1" - // For crash logging. - implementation 'io.sentry:sentry-android:6.13.1' - testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' From 34707787e2f639dfe133967eca3b1b7ba180aa7e Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 12:12:29 +0200 Subject: [PATCH 61/73] feat: update AndroidManifest.xml --- core/src/main/AndroidManifest.xml | 2 -- site/src/main/AndroidManifest.xml | 15 --------------- store/src/main/AndroidManifest.xml | 15 --------------- 3 files changed, 32 deletions(-) diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 5ea2e096c..1dbed5ebc 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -55,8 +55,6 @@ tools:overrideLibrary="com.google.zxing.client.android" tools:ignore="GoogleAppIndexingWarning, HardcodedDebugMode"> - - - - - - - - - diff --git a/store/src/main/AndroidManifest.xml b/store/src/main/AndroidManifest.xml index d368a0d19..1c30a764d 100644 --- a/store/src/main/AndroidManifest.xml +++ b/store/src/main/AndroidManifest.xml @@ -23,21 +23,6 @@ android:hasFragileUserData="false" tools:ignore="HardcodedDebugMode" > - - - - - - - Date: Tue, 13 Aug 2024 12:28:26 +0200 Subject: [PATCH 62/73] feat: update LoggingViewModel.kt --- .../prefs/EncryptedSettingsPreference.kt | 14 ---- .../net/ivpn/core/common/prefs/Settings.kt | 6 -- .../core/v2/viewmodel/LoggingViewModel.kt | 20 ----- .../res/layout/settings_section_logging.xml | 53 ------------- .../net/ivpn/client/SiteIVPNApplication.kt | 11 --- .../ivpn/client/sentry/SentryController.kt | 76 ------------------- .../net/ivpn/client/StoreIVPNApplication.kt | 11 --- .../ivpn/client/sentry/SentryController.kt | 76 ------------------- 8 files changed, 267 deletions(-) delete mode 100644 site/src/main/java/net/ivpn/client/sentry/SentryController.kt delete mode 100644 store/src/main/java/net/ivpn/client/sentry/SentryController.kt diff --git a/core/src/main/java/net/ivpn/core/common/prefs/EncryptedSettingsPreference.kt b/core/src/main/java/net/ivpn/core/common/prefs/EncryptedSettingsPreference.kt index 2a03545b8..aad4ff5ad 100644 --- a/core/src/main/java/net/ivpn/core/common/prefs/EncryptedSettingsPreference.kt +++ b/core/src/main/java/net/ivpn/core/common/prefs/EncryptedSettingsPreference.kt @@ -35,7 +35,6 @@ class EncryptedSettingsPreference @Inject constructor(val preference: Preference private const val IS_MIGRATED = "IS_MIGRATED" private const val SETTINGS_LOGGING = "SETTINGS_LOGGING" - private const val SETTINGS_SENTRY = "SETTINGS_SENTRY" private const val SETTINGS_MULTI_HOP = "SETTINGS_MULTI_HOP" private const val SETTINGS_MULTI_HOP_SAME_PROVIDER_ALLOWED = "SETTINGS_MULTI_HOP_SAME_PROVIDER_ALLOWED" private const val SETTINGS_KILL_SWITCH = "SETTINGS_KILL_SWITCH" @@ -452,16 +451,6 @@ class EncryptedSettingsPreference @Inject constructor(val preference: Preference return sharedPreferences.getString(LAST_USED_IP, null) } - fun enableSentry(value: Boolean) { - sharedPreferences.edit() - .putBoolean(SETTINGS_SENTRY, value) - .apply() - } - - fun isSentryEnabled(): Boolean { - return sharedPreferences.getBoolean(SETTINGS_SENTRY, false) - } - fun getFilter(): String? { return sharedPreferences.getString(SETTINGS_FILTER, null) } @@ -515,9 +504,6 @@ class EncryptedSettingsPreference @Inject constructor(val preference: Preference if (oldPreference.contains(SETTINGS_LOGGING)) { putSettingLogging(oldPreference.getBoolean(SETTINGS_LOGGING, false)) } - if (oldPreference.contains(SETTINGS_SENTRY)) { - enableSentry(oldPreference.getBoolean(SETTINGS_SENTRY, true)) - } if (oldPreference.contains(SETTINGS_MULTI_HOP)) { putSettingMultiHop(oldPreference.getBoolean(SETTINGS_MULTI_HOP, false)) } diff --git a/core/src/main/java/net/ivpn/core/common/prefs/Settings.kt b/core/src/main/java/net/ivpn/core/common/prefs/Settings.kt index ac9a539a3..ad5edc1bf 100644 --- a/core/src/main/java/net/ivpn/core/common/prefs/Settings.kt +++ b/core/src/main/java/net/ivpn/core/common/prefs/Settings.kt @@ -143,12 +143,6 @@ class Settings @Inject constructor( settingsPreference.putSettingStartOnBoot(value) } - var isSentryEnabled: Boolean - get() = settingsPreference.isSentryEnabled() - set(value) { - settingsPreference.enableSentry(value) - } - var isAntiSurveillanceEnabled: Boolean get() = settingsPreference.getIsAntiSurveillanceEnabled() set(value) { diff --git a/core/src/main/java/net/ivpn/core/v2/viewmodel/LoggingViewModel.kt b/core/src/main/java/net/ivpn/core/v2/viewmodel/LoggingViewModel.kt index f3cc00370..fd36c3531 100644 --- a/core/src/main/java/net/ivpn/core/v2/viewmodel/LoggingViewModel.kt +++ b/core/src/main/java/net/ivpn/core/v2/viewmodel/LoggingViewModel.kt @@ -39,19 +39,14 @@ class LoggingViewModel @Inject constructor( ) : ViewModel() { val isLoggingEnabled = ObservableBoolean() - val isCrashLoggingEnabled = ObservableBoolean() - val isSentrySupported = ObservableBoolean() var enableLoggingListener = CompoundButton.OnCheckedChangeListener { _: CompoundButton?, value: Boolean -> enableLogging(value) } - var enableCrashLoggingListener = CompoundButton.OnCheckedChangeListener { _: CompoundButton?, value: Boolean -> enableCrashLogging(value) } init { } fun onResume() { isLoggingEnabled.set(getLoggingValue()) - isCrashLoggingEnabled.set(isSentryEnabled()) - isSentrySupported.set(getSentrySupport()) } fun getLogFileUri(context: Context?): Uri { @@ -60,29 +55,14 @@ class LoggingViewModel @Inject constructor( fun reset() { isLoggingEnabled.set(getLoggingValue()) - isCrashLoggingEnabled.set(isSentryEnabled()) - isSentrySupported.set(getSentrySupport()) } private fun getLoggingValue(): Boolean { return logUtil.isLoggingEnabled } - private fun isSentryEnabled(): Boolean { - return IVPNApplication.crashLoggingController.isEnabled - } - - private fun getSentrySupport(): Boolean { - return IVPNApplication.crashLoggingController.isSupported - } - private fun enableLogging(value: Boolean) { isLoggingEnabled.set(value) logUtil.enableLogging(value) } - - private fun enableCrashLogging(value: Boolean) { - isCrashLoggingEnabled.set(value) - IVPNApplication.crashLoggingController.setState(value) - } } \ No newline at end of file diff --git a/core/src/main/res/layout/settings_section_logging.xml b/core/src/main/res/layout/settings_section_logging.xml index 2734fa6dc..14c079cc9 100644 --- a/core/src/main/res/layout/settings_section_logging.xml +++ b/core/src/main/res/layout/settings_section_logging.xml @@ -27,59 +27,6 @@ android:layout_height="wrap_content" android:text="@string/settings_logging" /> - - - - - - - - - - - - diff --git a/site/src/main/java/net/ivpn/client/SiteIVPNApplication.kt b/site/src/main/java/net/ivpn/client/SiteIVPNApplication.kt index 2f99c7b4c..916c931e3 100644 --- a/site/src/main/java/net/ivpn/client/SiteIVPNApplication.kt +++ b/site/src/main/java/net/ivpn/client/SiteIVPNApplication.kt @@ -26,7 +26,6 @@ import androidx.multidex.MultiDexApplication import net.ivpn.client.dagger.DaggerSiteComponent import net.ivpn.client.dagger.SiteComponent import net.ivpn.client.navigation.SiteNavigation -import net.ivpn.client.sentry.SentryController import net.ivpn.client.signup.SiteSignUpViewModel import net.ivpn.client.updates.UpdatesViewModel import net.ivpn.core.IVPNApplication @@ -44,9 +43,6 @@ class SiteIVPNApplication: MultiDexApplication() { @Inject lateinit var viewModel: SiteSignUpViewModel - @Inject - lateinit var sentry: SentryController - @Inject lateinit var updates: UpdatesViewModel @@ -56,8 +52,6 @@ class SiteIVPNApplication: MultiDexApplication() { val appComponent = IVPNApplication.initBy(this) initFeatureConfig() initComponents(appComponent) - //Init crash controller at first - initCrashLogging() initUpdatesController() IVPNApplication.initBaseComponents() initSignUpController() @@ -80,9 +74,4 @@ class SiteIVPNApplication: MultiDexApplication() { private fun initFeatureConfig() { IVPNApplication.applyFeatureConfig(SiteFeatureConfig()) } - - private fun initCrashLogging() { - sentry.init() - IVPNApplication.crashLoggingController = sentry - } } \ No newline at end of file diff --git a/site/src/main/java/net/ivpn/client/sentry/SentryController.kt b/site/src/main/java/net/ivpn/client/sentry/SentryController.kt deleted file mode 100644 index b53c40881..000000000 --- a/site/src/main/java/net/ivpn/client/sentry/SentryController.kt +++ /dev/null @@ -1,76 +0,0 @@ -package net.ivpn.client.sentry - -/* -IVPN Android app -https://github.com/ivpn/android-app - -Created by Oleksandr Mykhailenko. -Copyright (c) 2023 IVPN Limited. - -This file is part of the IVPN Android app. - -The IVPN Android app is free software: you can redistribute it and/or -modify it under the terms of the GNU General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) any later version. - -The IVPN Android app is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -details. - -You should have received a copy of the GNU General Public License -along with the IVPN Android app. If not, see . -*/ - -import io.sentry.SentryEvent -import io.sentry.SentryOptions.BeforeSendCallback -import io.sentry.android.core.SentryAndroid -import io.sentry.android.core.SentryAndroidOptions -import net.ivpn.client.dagger.SiteScope -import net.ivpn.core.IVPNApplication -import net.ivpn.core.common.logger.CrashLoggingController -import net.ivpn.core.common.prefs.Settings -import org.slf4j.LoggerFactory -import javax.inject.Inject - -@SiteScope -class SentryController @Inject internal constructor( - private val settings: Settings -) : CrashLoggingController() { - - override fun init() { - baseInit() - - SentryAndroid.init(IVPNApplication.application) { options: SentryAndroidOptions -> - // Add a callback that will be used before the event is sent to Sentry. - // With this callback, you can modify the event or, when returning null, also discard the event. - options.beforeSend = BeforeSendCallback { event: SentryEvent?, _: Any? -> - return@BeforeSendCallback if (isEnabled) { - LOGGER.info("Event was sent") - event - } else { - LOGGER.info("Event was NOT sent") - null - } - } - } - } - - override fun setState(isEnabled: Boolean) { - this.isEnabled = isEnabled - settings.isSentryEnabled = isEnabled - } - - override fun reset() { - baseInit() - } - - private fun baseInit() { - isSupported = true - isEnabled = settings.isSentryEnabled - } - - companion object { - private val LOGGER = LoggerFactory.getLogger(SentryController::class.java) - } -} \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/StoreIVPNApplication.kt b/store/src/main/java/net/ivpn/client/StoreIVPNApplication.kt index 0e0dbca20..895f26930 100644 --- a/store/src/main/java/net/ivpn/client/StoreIVPNApplication.kt +++ b/store/src/main/java/net/ivpn/client/StoreIVPNApplication.kt @@ -27,7 +27,6 @@ import net.ivpn.client.config.StoreFeatureConfig import net.ivpn.client.dagger.BillingComponent import net.ivpn.client.dagger.DaggerBillingComponent import net.ivpn.client.navigation.StoreNavigation -import net.ivpn.client.sentry.SentryController import net.ivpn.client.signup.SignUpViewModel import net.ivpn.client.updates.UpdatesStubViewModel import net.ivpn.core.IVPNApplication @@ -45,9 +44,6 @@ class StoreIVPNApplication: MultiDexApplication() { @Inject lateinit var viewModel: SignUpViewModel - @Inject - lateinit var sentry: SentryController - var updates = UpdatesStubViewModel() override fun onCreate() { @@ -57,8 +53,6 @@ class StoreIVPNApplication: MultiDexApplication() { initFeatureConfig() initComponents(appComponent) initUpdatesController() - //Init crash controller at first - initCrashLogging() IVPNApplication.initBaseComponents() initSignUpController() IVPNApplication.customNavigation = StoreNavigation @@ -80,9 +74,4 @@ class StoreIVPNApplication: MultiDexApplication() { private fun initFeatureConfig() { IVPNApplication.applyFeatureConfig(StoreFeatureConfig()) } - - private fun initCrashLogging() { - sentry.init() - IVPNApplication.crashLoggingController = sentry - } } \ No newline at end of file diff --git a/store/src/main/java/net/ivpn/client/sentry/SentryController.kt b/store/src/main/java/net/ivpn/client/sentry/SentryController.kt deleted file mode 100644 index 3485fee77..000000000 --- a/store/src/main/java/net/ivpn/client/sentry/SentryController.kt +++ /dev/null @@ -1,76 +0,0 @@ -package net.ivpn.client.sentry - -/* -IVPN Android app -https://github.com/ivpn/android-app - -Created by Oleksandr Mykhailenko. -Copyright (c) 2023 IVPN Limited. - -This file is part of the IVPN Android app. - -The IVPN Android app is free software: you can redistribute it and/or -modify it under the terms of the GNU General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) any later version. - -The IVPN Android app is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -details. - -You should have received a copy of the GNU General Public License -along with the IVPN Android app. If not, see . -*/ - -import io.sentry.SentryEvent -import io.sentry.SentryOptions.BeforeSendCallback -import io.sentry.android.core.SentryAndroid -import io.sentry.android.core.SentryAndroidOptions -import net.ivpn.client.dagger.BillingScope -import net.ivpn.core.IVPNApplication -import net.ivpn.core.common.logger.CrashLoggingController -import net.ivpn.core.common.prefs.Settings -import org.slf4j.LoggerFactory -import javax.inject.Inject - -@BillingScope -class SentryController @Inject internal constructor( - private val settings: Settings -) : CrashLoggingController() { - - override fun init() { - baseInit() - - SentryAndroid.init(IVPNApplication.application) { options: SentryAndroidOptions -> - // Add a callback that will be used before the event is sent to Sentry. - // With this callback, you can modify the event or, when returning null, also discard the event. - options.beforeSend = BeforeSendCallback { event: SentryEvent?, _: Any? -> - return@BeforeSendCallback if (isEnabled) { - LOGGER.info("Event was sent") - event - } else { - LOGGER.info("Event was NOT sent") - null - } - } - } - } - - override fun setState(isEnabled: Boolean) { - this.isEnabled = isEnabled - settings.isSentryEnabled = isEnabled - } - - override fun reset() { - baseInit() - } - - private fun baseInit() { - isSupported = true - isEnabled = settings.isSentryEnabled - } - - companion object { - private val LOGGER = LoggerFactory.getLogger(SentryController::class.java) - } -} \ No newline at end of file From 987f776028d64781d54479dd9f15752f1c389b56 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 12:33:37 +0200 Subject: [PATCH 63/73] feat: remove CrashLoggingController.kt --- .../java/net/ivpn/core/IVPNApplication.kt | 6 ---- .../common/logger/CrashLoggingController.kt | 35 ------------------ .../ivpn/core/common/utils/ComponentUtil.java | 1 - core/src/main/res/values/strings.xml | 2 -- .../net/ivpn/client/FDroidIVPNApplication.kt | 10 ------ .../logging/StubCrashLoggingController.kt | 36 ------------------- 6 files changed, 90 deletions(-) delete mode 100644 core/src/main/java/net/ivpn/core/common/logger/CrashLoggingController.kt delete mode 100644 fdroid/src/main/java/net/ivpn/client/logging/StubCrashLoggingController.kt diff --git a/core/src/main/java/net/ivpn/core/IVPNApplication.kt b/core/src/main/java/net/ivpn/core/IVPNApplication.kt index 21518c426..cd0e45e96 100644 --- a/core/src/main/java/net/ivpn/core/IVPNApplication.kt +++ b/core/src/main/java/net/ivpn/core/IVPNApplication.kt @@ -7,7 +7,6 @@ import androidx.navigation.NavGraph import net.ivpn.core.common.FeatureConfig import net.ivpn.core.common.dagger.ApplicationComponent import net.ivpn.core.common.dagger.DaggerApplicationComponent -import net.ivpn.core.common.logger.CrashLoggingController import net.ivpn.core.common.navigation.CustomNavigation import net.ivpn.core.v2.signup.SignUpController import net.ivpn.core.v2.updates.UpdatesController @@ -42,7 +41,6 @@ object IVPNApplication { lateinit var updatesController: UpdatesController lateinit var customNavigation: CustomNavigation lateinit var moduleNavGraph: NavGraph - lateinit var crashLoggingController: CrashLoggingController lateinit var config: FeatureConfig fun initBy(application: Application): ApplicationComponent{ @@ -67,10 +65,6 @@ object IVPNApplication { updatesController = controller } - fun applyCrashController(crashController: CrashLoggingController) { - this.crashLoggingController = crashController - } - fun applyFeatureConfig(config: FeatureConfig) { this.config = config } diff --git a/core/src/main/java/net/ivpn/core/common/logger/CrashLoggingController.kt b/core/src/main/java/net/ivpn/core/common/logger/CrashLoggingController.kt deleted file mode 100644 index 07bbb96ad..000000000 --- a/core/src/main/java/net/ivpn/core/common/logger/CrashLoggingController.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.ivpn.core.common.logger - -/* - IVPN Android app - https://github.com/ivpn/android-app - - Created by Oleksandr Mykhailenko. - Copyright (c) 2023 IVPN Limited. - - This file is part of the IVPN Android app. - - The IVPN Android app is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) any later version. - - The IVPN Android app is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - You should have received a copy of the GNU General Public License - along with the IVPN Android app. If not, see . -*/ - -abstract class CrashLoggingController { - - var isEnabled: Boolean = false - var isSupported: Boolean = false - - abstract fun init() - - abstract fun setState(isEnabled: Boolean) - - abstract fun reset() -} \ No newline at end of file diff --git a/core/src/main/java/net/ivpn/core/common/utils/ComponentUtil.java b/core/src/main/java/net/ivpn/core/common/utils/ComponentUtil.java index 3585cf175..aa9b003d8 100644 --- a/core/src/main/java/net/ivpn/core/common/utils/ComponentUtil.java +++ b/core/src/main/java/net/ivpn/core/common/utils/ComponentUtil.java @@ -105,7 +105,6 @@ public void resetComponents() { protocolController.reset(); IVPNApplication.updatesController.resetComponent(); logUtil.resetAll(); - IVPNApplication.crashLoggingController.reset(); mockLocationController.reset(); NotificationManagerCompat.from(IVPNApplication.application).cancelAll(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5ed3eb741..4acef3615 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -43,7 +43,6 @@ VERSION Color theme Enable logging - Enable crash logging Multi-hop connection Multi-hop same provider restriction Allow to use servers from the same provider to build Multi-hop chain. @@ -56,7 +55,6 @@ SEND LOGS Split tunneling We can\'t see these until you send them to us. - Anonymous crash logs will be sent to IVPN to help us improve the application. Choose which apps you want to use with IVPN. Allow using internet only when IVPN connection is enabled. Can help to improve protection. diff --git a/fdroid/src/main/java/net/ivpn/client/FDroidIVPNApplication.kt b/fdroid/src/main/java/net/ivpn/client/FDroidIVPNApplication.kt index d93dc8e66..176e38f60 100644 --- a/fdroid/src/main/java/net/ivpn/client/FDroidIVPNApplication.kt +++ b/fdroid/src/main/java/net/ivpn/client/FDroidIVPNApplication.kt @@ -25,7 +25,6 @@ package net.ivpn.client import androidx.multidex.MultiDexApplication import net.ivpn.client.dagger.DaggerFDroidComponent import net.ivpn.client.dagger.FDroidComponent -import net.ivpn.client.logging.StubCrashLoggingController import net.ivpn.client.navigation.FDroidNavigation import net.ivpn.client.signup.FDroidSignUpViewModel import net.ivpn.client.updates.StubUpdatesViewModel @@ -44,8 +43,6 @@ class FDroidIVPNApplication: MultiDexApplication() { @Inject lateinit var signup: FDroidSignUpViewModel - var crashController = StubCrashLoggingController() - var updates = StubUpdatesViewModel() override fun onCreate() { @@ -55,8 +52,6 @@ class FDroidIVPNApplication: MultiDexApplication() { initFeatureConfig() initComponents(appComponent) initUpdatesController() - //Init crash controller at first - initCrashLogging() IVPNApplication.initBaseComponents() initSignUpController() IVPNApplication.customNavigation = FDroidNavigation() @@ -78,9 +73,4 @@ class FDroidIVPNApplication: MultiDexApplication() { private fun initFeatureConfig() { IVPNApplication.applyFeatureConfig(FDroidFeatureConfig()) } - - private fun initCrashLogging() { - crashController.init() - IVPNApplication.crashLoggingController = crashController - } } \ No newline at end of file diff --git a/fdroid/src/main/java/net/ivpn/client/logging/StubCrashLoggingController.kt b/fdroid/src/main/java/net/ivpn/client/logging/StubCrashLoggingController.kt deleted file mode 100644 index 6de6f07be..000000000 --- a/fdroid/src/main/java/net/ivpn/client/logging/StubCrashLoggingController.kt +++ /dev/null @@ -1,36 +0,0 @@ -package net.ivpn.client.logging - -/* - IVPN Android app - https://github.com/ivpn/android-app - - Created by Oleksandr Mykhailenko. - Copyright (c) 2023 IVPN Limited. - - This file is part of the IVPN Android app. - - The IVPN Android app is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) any later version. - - The IVPN Android app is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - You should have received a copy of the GNU General Public License - along with the IVPN Android app. If not, see . -*/ - -import net.ivpn.core.common.logger.CrashLoggingController - -class StubCrashLoggingController : CrashLoggingController() { - override fun init() { - } - - override fun setState(isEnabled: Boolean) { - } - - override fun reset() { - } -} \ No newline at end of file From 802eb01b5dfb3bfcee6f6afe5592844cec5319bb Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 13:24:26 +0200 Subject: [PATCH 64/73] feat: fdroid app icon --- fastlane/metadata/android/en-US/images/icon.png | Bin 0 -> 10045 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fastlane/metadata/android/en-US/images/icon.png diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a15d96b7cea679913edc1256fd2f84b3a1260148 GIT binary patch literal 10045 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 TlM^1|00000NkvXXu0mjfn*kUf literal 0 HcmV?d00001 From 808ed82693ac101d3b050deb45c343d719dfb5c2 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 13:49:10 +0200 Subject: [PATCH 65/73] feat: update fdroid app icon --- .../metadata/android/en-US/images/icon.png | Bin 10045 -> 7985 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png index a15d96b7cea679913edc1256fd2f84b3a1260148..8ce40e9afd7a8f41e184dde3879612fbf7e000c0 100644 GIT binary patch literal 7985 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 TlM^1|00000NkvXXu0mjfn*kUf From b22bb597d4d1adab5f54da3ca676915d29d85bdb Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 14:52:39 +0200 Subject: [PATCH 66/73] fix: update AndroidManifest.xml --- core/src/main/AndroidManifest.xml | 8 ++++++-- site/src/main/AndroidManifest.xml | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 5ea2e096c..85e8f9dfa 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -100,12 +100,15 @@ android:exported="false" android:permission="android.permission.BIND_VPN_SERVICE" android:foregroundServiceType="specialUse" /> - + @@ -128,6 +131,7 @@ android:icon="@drawable/ic_logo_sq" android:label="@string/app_name" android:exported="true" + android:foregroundServiceType="specialUse" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> diff --git a/site/src/main/AndroidManifest.xml b/site/src/main/AndroidManifest.xml index d90551798..47a25f33c 100644 --- a/site/src/main/AndroidManifest.xml +++ b/site/src/main/AndroidManifest.xml @@ -5,9 +5,12 @@ - + + + + From b6c9cb21c423628f18a6a39fa71d978389181a55 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 15:09:03 +0200 Subject: [PATCH 67/73] chore: update app version and build number --- core/build.gradle | 4 ++-- fdroid/build.gradle | 4 ++-- liboqs-android/build.gradle | 4 ++-- site/build.gradle | 4 ++-- store/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index fc2c11db7..f405452bc 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,8 +30,8 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 134 - versionName "2.10.9" + versionCode 135 + versionName "2.10.10" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/fdroid/build.gradle b/fdroid/build.gradle index 53f2b62f2..43389da7a 100644 --- a/fdroid/build.gradle +++ b/fdroid/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 134 - versionName "2.10.9" + versionCode 135 + versionName "2.10.10" ndkVersion "25.1.8937393" buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] diff --git a/liboqs-android/build.gradle b/liboqs-android/build.gradle index 1e7d6d3b7..3c798d1b6 100644 --- a/liboqs-android/build.gradle +++ b/liboqs-android/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 34 - versionCode 134 - versionName "2.10.9" + versionCode 135 + versionName "2.10.10" ndkVersion "25.1.8937393" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/site/build.gradle b/site/build.gradle index f880b8d1f..48f0ddd8c 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -31,8 +31,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 134 - versionName "2.10.9" + versionCode 135 + versionName "2.10.10" ndkVersion "25.1.8937393" buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] diff --git a/store/build.gradle b/store/build.gradle index a1f748134..31e1678f0 100644 --- a/store/build.gradle +++ b/store/build.gradle @@ -32,8 +32,8 @@ android { applicationId "net.ivpn.client" minSdkVersion 23 targetSdkVersion 34 - versionCode 134 - versionName "2.10.9" + versionCode 135 + versionName "2.10.10" ndkVersion "25.1.8937393" buildConfigField "String", "BILLING_PUBLIC_KEY", keystoreProperties['billing.public.key'] From cf8ec08c7bb40d878e158150abb0793a1ed6aecb Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 13 Aug 2024 15:20:12 +0200 Subject: [PATCH 68/73] fix: update ServersPreference.kt --- .../net/ivpn/core/common/prefs/ServersPreference.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/net/ivpn/core/common/prefs/ServersPreference.kt b/core/src/main/java/net/ivpn/core/common/prefs/ServersPreference.kt index efe84ed30..281b6dd66 100644 --- a/core/src/main/java/net/ivpn/core/common/prefs/ServersPreference.kt +++ b/core/src/main/java/net/ivpn/core/common/prefs/ServersPreference.kt @@ -139,15 +139,15 @@ class ServersPreference @Inject constructor( fun setCurrentServer(serverType: ServerType?, server: Server?) { if (serverType == null || server == null) return - val openvpnServer = openvpnServersList?.first { it == server } - val wireguardServer = wireguardServersList?.first { it == server } + val openvpnServer = openvpnServersList?.firstOrNull { it == server } + val wireguardServer = wireguardServersList?.firstOrNull { it == server } val serverKey = if (serverType == ServerType.ENTRY) CURRENT_ENTER_SERVER else CURRENT_EXIT_SERVER preference.serversSharedPreferences.edit() - .putString(serverKey, Mapper.from(openvpnServer)) - .apply() + .putString(serverKey, Mapper.from(openvpnServer)) + .apply() preference.wireguardServersSharedPreferences.edit() - .putString(serverKey, Mapper.from(wireguardServer)) - .apply() + .putString(serverKey, Mapper.from(wireguardServer)) + .apply() } fun putOpenVpnServerList(servers: List?) { From c622aa8f0b145169f5503da5bdd11067cf9eb689 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Thu, 15 Aug 2024 16:31:07 +0200 Subject: [PATCH 69/73] fix: update IVPNTileService.kt --- core/src/main/java/net/ivpn/core/common/tile/IVPNTileService.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/net/ivpn/core/common/tile/IVPNTileService.kt b/core/src/main/java/net/ivpn/core/common/tile/IVPNTileService.kt index b4a9cbaae..10bd6a9b2 100644 --- a/core/src/main/java/net/ivpn/core/common/tile/IVPNTileService.kt +++ b/core/src/main/java/net/ivpn/core/common/tile/IVPNTileService.kt @@ -121,6 +121,8 @@ class IVPNTileService: TileService() { val vpnIntent = Intent(this, PermissionActivity::class.java) vpnIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(vpnIntent) + + connect.connectIfNot() } tile.updateTile() From 309f1bbf730971ffbb92d8bfc27c682858326ffa Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 16 Aug 2024 11:37:57 +0200 Subject: [PATCH 70/73] fix: update UpdatesService.java --- site/src/main/java/net/ivpn/client/updates/UpdatesService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/src/main/java/net/ivpn/client/updates/UpdatesService.java b/site/src/main/java/net/ivpn/client/updates/UpdatesService.java index c0a9b1a17..a6f58c6c2 100644 --- a/site/src/main/java/net/ivpn/client/updates/UpdatesService.java +++ b/site/src/main/java/net/ivpn/client/updates/UpdatesService.java @@ -90,14 +90,12 @@ public int onStartCommand(Intent intent, int flags, int startId) { switch (action) { case UPDATE_PROCEED: { - closeSystemDialogs(); return doSendActionBroadcast(UPDATE_PROCEED); } case UPDATE_SKIP: { return doSendActionBroadcast(UPDATE_SKIP); } case UPDATE_SETTINGS: { - closeSystemDialogs(); return doSendActionBroadcast(UPDATE_SETTINGS); } case SHOW_UPDATE_NOTIFICATION: { From 5b3272f1d8b13aca45a7b3cf3097d41af073833a Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 20 Aug 2024 10:27:19 +0200 Subject: [PATCH 71/73] docs: update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9555509b9..ff2de0c47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## Version 2.10.10 - Unreleased + +[FIXED] Crash when using Network Protection +[FIXED] Crash when using the Update button +[FIXED] Connect VPN using the Quick Settings tile +[NOTE] Removed option to report crash logs with Sentry + ## Version 2.10.9 - 2024-08-08 [IMPROVED] Target Android API level 34 From 2b9d3759e32dcc44dfffcf9f1418f3c1624177c0 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 20 Aug 2024 12:06:48 +0200 Subject: [PATCH 72/73] docs: update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff2de0c47..42117c080 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,16 @@ All notable changes to this project will be documented in this file. -## Version 2.10.10 - Unreleased +## Version 2.10.10 - 2024-08-20 [FIXED] Crash when using Network Protection [FIXED] Crash when using the Update button [FIXED] Connect VPN using the Quick Settings tile [NOTE] Removed option to report crash logs with Sentry +[Download IVPN Client v2.10.10](https://www.ivpn.net/releases/android/IVPNv2.10.10site.apk) +SHA256: 484ede3adabda94bc78768d3f3b1dc12732cbb76eb886216bc693850a469f5fe + ## Version 2.10.9 - 2024-08-08 [IMPROVED] Target Android API level 34 From d04b3f09849f672f313f52c1b183cbb0e65f340c Mon Sep 17 00:00:00 2001 From: Rolando Townsend Date: Fri, 20 Sep 2024 14:18:55 +0000 Subject: [PATCH 73/73] strings.xml: Fix spelling of "Wi-Fi" and "Account ID" Fix spelling of "Wi-Fi" and "Account ID" --- core/src/main/res/values/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index f6ad04710..018f34d8d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -208,7 +208,7 @@ Disconnect from IVPN Disable kill-switch Mark one of the scanned network as TRUSTED or UNTRUSTED to add it here - Once we find a WiFi networks they will be displayed here + Once we find Wi-Fi networks they will be displayed here Current network @@ -629,7 +629,7 @@ Your account has been created. - Account Id + Account ID Active Inactive Account type @@ -655,4 +655,4 @@ Multi-Hop connections]]> No active subscription FASTEST - \ No newline at end of file +