summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-06-08 11:32:50 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-06-08 11:32:50 -0300
commit3a35547e4c4a00755b14d05f67ae5e636138f81b (patch)
treea98efa895b28d20d5198e4706fe64fe7850389a9 /android
parent05be799e63292f87d96f5a85f3cc97f94b578e08 (diff)
parent6b88c972af86ee7d941e995795ddf46c418d3b05 (diff)
downloadmullvadvpn-3a35547e4c4a00755b14d05f67ae5e636138f81b.tar.xz
mullvadvpn-3a35547e4c4a00755b14d05f67ae5e636138f81b.zip
Merge branch 'show-time-running-out-banner'
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt4
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/NotificationBanner.kt89
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RemainingTimeLabel.kt19
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/util/TimeLeftFormatter.kt38
-rw-r--r--android/src/main/res/values/strings.xml1
5 files changed, 98 insertions, 53 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt
index 36cf498e40..1ef0b3ac62 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt
@@ -102,6 +102,10 @@ class ConnectFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) {
} else if (expiry != null) {
scheduleNextAccountExpiryCheck(expiry)
}
+
+ jobTracker.newUiJob("updateAccountExpiry") {
+ notificationBanner.accountExpiry = expiry
+ }
}
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/NotificationBanner.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/NotificationBanner.kt
index 447837fefd..82a45cb347 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/NotificationBanner.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/NotificationBanner.kt
@@ -18,10 +18,12 @@ import net.mullvad.mullvadvpn.dataproxy.AppVersionInfoCache
import net.mullvad.mullvadvpn.model.KeygenEvent
import net.mullvad.mullvadvpn.model.TunnelState
import net.mullvad.mullvadvpn.service.MullvadDaemon
+import net.mullvad.mullvadvpn.util.TimeLeftFormatter
import net.mullvad.talpid.tunnel.ActionAfterDisconnect
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.tunnel.ErrorStateCause
import net.mullvad.talpid.tunnel.ParameterGenerationError
+import org.joda.time.DateTime
class NotificationBanner(
val parentView: View,
@@ -29,12 +31,18 @@ class NotificationBanner(
val versionInfoCache: AppVersionInfoCache,
val daemon: MullvadDaemon
) {
- enum class ExternalLink { Download, KeyManagement }
+ enum class ExternalLink {
+ BuyMoreTime,
+ Download,
+ KeyManagement
+ }
private val resources = context.resources
+ private val timeLeftFormatter = TimeLeftFormatter(resources)
- private val keyManagementUrl = context.getString(R.string.wg_key_url)
+ private val buyMoreTimeUrl = context.getString(R.string.account_url)
private val downloadUrl = Uri.parse(context.getString(R.string.download_url))
+ private val keyManagementUrl = context.getString(R.string.wg_key_url)
private val errorImage = resources.getDrawable(R.drawable.icon_notification_error, null)
private val warningImage = resources.getDrawable(R.drawable.icon_notification_warning, null)
@@ -56,7 +64,7 @@ class NotificationBanner(
private var externalLink: ExternalLink? = null
private var visible = false
- private val keyManagementController = BlockingController(
+ private val clickController = BlockingController(
object : BlockableView {
override fun setEnabled(enabled: Boolean) {
if (enabled) {
@@ -68,13 +76,20 @@ class NotificationBanner(
}
}
- override fun onClick(): Job {
- return GlobalScope.launch(Dispatchers.Default) {
- val token = daemon.getWwwAuthToken()
- val url = Uri.parse(keyManagementUrl + "?token=" + token)
+ override fun onClick() = GlobalScope.launch(Dispatchers.Default) {
+ buildUrl()?.let { url ->
context.startActivity(Intent(Intent.ACTION_VIEW, url))
}
}
+
+ private fun buildUrl() = when (externalLink) {
+ ExternalLink.BuyMoreTime -> Uri.parse(buyMoreTimeUrl + buildUrlTokenParameter())
+ ExternalLink.Download -> downloadUrl
+ ExternalLink.KeyManagement -> Uri.parse(keyManagementUrl + buildUrlTokenParameter())
+ null -> null
+ }
+
+ private fun buildUrlTokenParameter() = "?token=${daemon.getWwwAuthToken()}"
}
)
@@ -82,20 +97,12 @@ class NotificationBanner(
newListener?.invoke(height)
}
- var keyState: KeygenEvent? = null
- set(value) {
- field = value
- update()
- }
-
- var tunnelState: TunnelState = TunnelState.Disconnected()
- set(value) {
- field = value
- update()
- }
+ var accountExpiry by observable<DateTime?>(null) { _, _, _ -> update() }
+ var keyState by observable<KeygenEvent?>(null) { _, _, _ -> update() }
+ var tunnelState by observable<TunnelState>(TunnelState.Disconnected()) { _, _, _ -> update() }
init {
- banner.setOnClickListener { onClick() }
+ banner.setOnClickListener { clickController.action() }
}
fun onResume() {
@@ -107,12 +114,16 @@ class NotificationBanner(
fun onPause() {
versionInfoCache.onUpdate = null
updateJob?.cancel()
- keyManagementController.onPause()
+ clickController.onPause()
}
private fun update() {
externalLink = null
- updateBasedOnTunnelState() || updateBasedOnKeyState() || updateBasedOnVersionInfo()
+
+ updateBasedOnTunnelState() ||
+ updateBasedOnKeyState() ||
+ updateBasedOnVersionInfo() ||
+ updateBasedOnAccountExpiry()
}
private fun updateBasedOnKeyState(): Boolean {
@@ -153,9 +164,7 @@ class NotificationBanner(
}
private fun updateBasedOnVersionInfo(): Boolean {
- if (!versionInfoCache.isOutdated && versionInfoCache.isSupported) {
- hide()
- } else {
+ if (versionInfoCache.isOutdated || !versionInfoCache.isSupported) {
val title: Int
val statusImage: Drawable
val template: Int
@@ -176,6 +185,25 @@ class NotificationBanner(
externalLink = ExternalLink.Download
show(statusImage, title, description)
+
+ return true
+ } else {
+ return false
+ }
+ }
+
+ private fun updateBasedOnAccountExpiry(): Boolean {
+ val expiry = accountExpiry
+ val threeDaysFromNow = DateTime.now().plusDays(3)
+
+ if (expiry != null && expiry.isBefore(threeDaysFromNow)) {
+ val timeLeft = timeLeftFormatter.format(expiry)
+
+ externalLink = ExternalLink.BuyMoreTime
+
+ show(warningImage, R.string.account_credit_expires_soon, timeLeft)
+ } else {
+ hide()
}
return true
@@ -277,17 +305,4 @@ class NotificationBanner(
return measuredHeight
}
}
-
- private fun onClick() {
- val externalLink = this.externalLink
-
- when (externalLink) {
- ExternalLink.Download -> {
- context.startActivity(Intent(Intent.ACTION_VIEW, this.downloadUrl))
- }
- ExternalLink.KeyManagement -> {
- this.keyManagementController.action()
- }
- }
- }
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RemainingTimeLabel.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RemainingTimeLabel.kt
index f20f6974fd..20a5c62e6e 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RemainingTimeLabel.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/RemainingTimeLabel.kt
@@ -4,12 +4,13 @@ import android.content.Context
import android.view.View
import android.widget.TextView
import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.util.TimeLeftFormatter
import org.joda.time.DateTime
import org.joda.time.Duration
-import org.joda.time.PeriodType
class RemainingTimeLabel(val context: Context, val view: View) {
private val resources = context.resources
+ private val formatter = TimeLeftFormatter(resources)
private val expiredColor = resources.getColor(R.color.red)
private val normalColor = resources.getColor(R.color.white60)
@@ -32,21 +33,7 @@ class RemainingTimeLabel(val context: Context, val view: View) {
label.setText(R.string.out_of_time)
label.setTextColor(expiredColor)
} else {
- val remainingTimeInfo =
- remainingTime.toPeriodTo(expiry, PeriodType.yearMonthDayTime())
-
- if (remainingTimeInfo.years > 0) {
- label.setText(getRemainingText(R.plurals.years_left, remainingTimeInfo.years))
- } else if (remainingTimeInfo.months >= 3) {
- label.setText(getRemainingText(R.plurals.months_left, remainingTimeInfo.months))
- } else if (remainingTimeInfo.months > 0 || remainingTimeInfo.days >= 1) {
- label.setText(
- getRemainingText(R.plurals.days_left, remainingTime.standardDays.toInt())
- )
- } else {
- label.setText(R.string.less_than_a_day_left)
- }
-
+ label.setText(formatter.format(expiry, remainingTime))
label.setTextColor(normalColor)
}
} else {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/util/TimeLeftFormatter.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/TimeLeftFormatter.kt
new file mode 100644
index 0000000000..c3a6aaa1cb
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/TimeLeftFormatter.kt
@@ -0,0 +1,38 @@
+package net.mullvad.mullvadvpn.util
+
+import android.content.res.Resources
+import net.mullvad.mullvadvpn.R
+import org.joda.time.DateTime
+import org.joda.time.Duration
+import org.joda.time.PeriodType
+
+class TimeLeftFormatter(val resources: Resources) {
+ fun format(accountExpiry: DateTime): String {
+ val remainingTime = Duration(DateTime.now(), accountExpiry)
+
+ return format(accountExpiry, remainingTime)
+ }
+
+ fun format(accountExpiry: DateTime, remainingTime: Duration): String {
+ if (remainingTime.isShorterThan(Duration.ZERO)) {
+ return resources.getString(R.string.out_of_time)
+ } else {
+ val remainingTimeInfo =
+ remainingTime.toPeriodTo(accountExpiry, PeriodType.yearMonthDayTime())
+
+ if (remainingTimeInfo.years > 0) {
+ return getRemainingText(R.plurals.years_left, remainingTimeInfo.years)
+ } else if (remainingTimeInfo.months >= 3) {
+ return getRemainingText(R.plurals.months_left, remainingTimeInfo.months)
+ } else if (remainingTimeInfo.months > 0 || remainingTimeInfo.days >= 1) {
+ return getRemainingText(R.plurals.days_left, remainingTime.standardDays.toInt())
+ } else {
+ return resources.getString(R.string.less_than_a_day_left)
+ }
+ }
+ }
+
+ private fun getRemainingText(pluralId: Int, quantity: Int): String {
+ return resources.getQuantityString(pluralId, quantity, quantity)
+ }
+}
diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml
index 86cca30416..1bdf764ac4 100644
--- a/android/src/main/res/values/strings.xml
+++ b/android/src/main/res/values/strings.xml
@@ -130,6 +130,7 @@
<string name="unsupported_version">Unsupported version</string>
<string name="unsupported_version_description">You are running an unsupported app version.
Please upgrade to %1$s now to ensure your security</string>
+ <string name="account_credit_expires_soon">Account credit expires soon</string>
<string name="select_location">Select location</string>
<string name="select_location_description">While connected, your real location is masked with a
private and secure location in the selected region</string>