summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/TimeSinceLabel.kt59
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/WireguardKeyFragment.kt66
-rw-r--r--android/src/main/res/layout/wireguard_key.xml83
3 files changed, 39 insertions, 169 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/TimeSinceLabel.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/TimeSinceLabel.kt
deleted file mode 100644
index 8d2e0aa2f3..0000000000
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/TimeSinceLabel.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package net.mullvad.mullvadvpn.ui
-
-import android.content.Context
-import android.view.View
-import android.widget.TextView
-import net.mullvad.mullvadvpn.R
-import org.joda.time.DateTime
-import org.joda.time.Duration
-import org.joda.time.PeriodType
-
-class TimeSinceLabel(val context: Context, val view: View) {
- private val resources = context.resources
- private val label = view.findViewById<TextView>(R.id.time_since)
-
- private val periodType = PeriodType.standard()
- .withMillisRemoved()
- .withSecondsRemoved()
-
- var timeInstant: DateTime? = null
- set(value) {
- field = value
- updateLabel()
- }
-
- var visibility
- get() = label.visibility
- set(value) {
- label.visibility = value
- }
-
- private fun updateLabel() {
- val instant = timeInstant
-
- if (instant != null) {
- val elapsedTime = Duration(instant, DateTime.now())
- val elapsedTimeInfo = elapsedTime.toPeriodTo(instant, periodType)
-
- if (elapsedTimeInfo.years > 0) {
- label.setText(getRemainingText(R.plurals.years_ago, elapsedTimeInfo.years))
- } else if (elapsedTimeInfo.months > 0) {
- label.setText(getRemainingText(R.plurals.months_ago, elapsedTimeInfo.months))
- } else if (elapsedTimeInfo.days > 0) {
- label.setText(getRemainingText(R.plurals.days_ago, elapsedTimeInfo.days))
- } else if (elapsedTimeInfo.hours > 0) {
- label.setText(getRemainingText(R.plurals.hours_ago, elapsedTimeInfo.hours))
- } else if (elapsedTimeInfo.minutes > 0) {
- label.setText(getRemainingText(R.plurals.minutes_ago, elapsedTimeInfo.minutes))
- } else {
- label.setText(R.string.less_than_a_minute_ago)
- }
- } else {
- label.text = ""
- }
- }
-
- private fun getRemainingText(pluralId: Int, quantity: Int): String {
- return resources.getQuantityString(pluralId, quantity, quantity)
- }
-}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/WireguardKeyFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/WireguardKeyFragment.kt
index 0a8f341929..19358ab990 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/WireguardKeyFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/WireguardKeyFragment.kt
@@ -1,7 +1,5 @@
package net.mullvad.mullvadvpn.ui
-import android.content.ClipData
-import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
@@ -21,6 +19,7 @@ import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.model.KeygenEvent
import net.mullvad.mullvadvpn.model.KeygenFailure
import net.mullvad.mullvadvpn.model.TunnelState
+import net.mullvad.mullvadvpn.util.TimeAgoFormatter
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormat
@@ -28,6 +27,8 @@ import org.joda.time.format.DateTimeFormat
val RFC3339_FORMAT = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss.SSSSSSSSSS z")
class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) {
+ private lateinit var timeAgoFormatter: TimeAgoFormatter
+
private var currentJob: Job? = null
private var updateViewsJob: Job? = null
private var tunnelStateListener: Int? = null
@@ -48,12 +49,9 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
}
}
- private lateinit var publicKey: TextView
- private lateinit var publicKeyAge: TimeSinceLabel
- private lateinit var publicKeyContainer: View
+ private lateinit var publicKey: CopyableInformationView
+ private lateinit var keyAge: InformationView
private lateinit var statusMessage: TextView
- private lateinit var publicKeySpinner: View
- private lateinit var timeSinceSpinner: View
private lateinit var verifyingKeySpinner: View
private lateinit var manageKeysButton: Button
private lateinit var generateKeyButton: android.widget.Button
@@ -70,6 +68,12 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
}
}
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+
+ timeAgoFormatter = TimeAgoFormatter(context.resources)
+ }
+
override fun onSafelyCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -83,15 +87,8 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
statusMessage = view.findViewById<TextView>(R.id.wireguard_key_status)
manageKeysButton = view.findViewById(R.id.manage_keys)
- publicKey = view.findViewById<TextView>(R.id.wireguard_public_key)
-
- publicKeyAge = TimeSinceLabel(parentActivity, view)
-
- publicKeyContainer = view.findViewById<View>(R.id.public_key_container).apply {
- setOnClickListener {
- copyPublicKeyToClipboard()
- }
- }
+ publicKey = view.findViewById(R.id.public_key)
+ keyAge = view.findViewById(R.id.key_age)
generateKeyButton = view.findViewById<Button>(R.id.generate_key).apply {
setOnClickListener {
@@ -105,8 +102,6 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
}
}
- publicKeySpinner = view.findViewById(R.id.public_key_spinner)
- timeSinceSpinner = view.findViewById(R.id.time_since_spinner)
verifyingKeySpinner = view.findViewById(R.id.verifying_key_spinner)
val keyUrl = parentActivity.getString(R.string.wg_key_url)
@@ -148,18 +143,18 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
when (val keyState = keyStatusListener.keyStatus) {
null -> {
- publicKey.visibility = View.INVISIBLE
+ publicKey.information = null
}
is KeygenEvent.NewKey -> {
val key = keyState.publicKey
val publicKeyString = Base64.encodeToString(key.key, Base64.NO_WRAP)
- publicKey.visibility = View.VISIBLE
- publicKey.setText(publicKeyString.substring(0, 20) + "...")
-
- publicKeyAge.timeInstant =
+ val publicKeyAge =
DateTime.parse(key.dateCreated, RFC3339_FORMAT).withZone(DateTimeZone.UTC)
+ publicKey.information = publicKeyString.substring(0, 20) + "..."
+ keyAge.information = timeAgoFormatter.format(publicKeyAge)
+
keyState.verified?.let { verified ->
if (verified) {
setStatusMessage(R.string.wireguard_key_valid, R.color.green)
@@ -233,18 +228,6 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
}
}
- private fun copyPublicKeyToClipboard() {
- val clipboard =
- parentActivity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- val clipLabel = parentActivity.resources.getString(R.string.wireguard_public_key)
- val clipData = ClipData.newPlainText(clipLabel, publicKey.text)
-
- clipboard.primaryClip = clipData
-
- Toast.makeText(parentActivity, R.string.copied_wireguard_public_key, Toast.LENGTH_SHORT)
- .show()
- }
-
private fun onGenerateKeyPress() {
currentJob?.cancel()
@@ -257,20 +240,11 @@ class WireguardKeyFragment : ServiceDependentFragment(OnNoService.GoToLaunchScre
updateViews()
currentJob = GlobalScope.launch(Dispatchers.Main) {
- publicKeyContainer.setEnabled(false)
- publicKey.visibility = View.INVISIBLE
- publicKeyAge.visibility = View.INVISIBLE
- timeSinceSpinner.visibility = View.VISIBLE
- publicKeySpinner.visibility = View.VISIBLE
+ publicKey.information = null
+ keyAge.information = null
keyStatusListener.generateKey().join()
- publicKeySpinner.visibility = View.INVISIBLE
- timeSinceSpinner.visibility = View.INVISIBLE
- publicKeyAge.visibility = View.VISIBLE
- publicKey.visibility = View.VISIBLE
- publicKeyContainer.setEnabled(true)
-
generatingKey = false
updateViews()
}
diff --git a/android/src/main/res/layout/wireguard_key.xml b/android/src/main/res/layout/wireguard_key.xml
index 2afacd8ada..59a79a4179 100644
--- a/android/src/main/res/layout/wireguard_key.xml
+++ b/android/src/main/res/layout/wireguard_key.xml
@@ -1,4 +1,5 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:mullvad="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/darkBlue"
@@ -36,70 +37,24 @@
android:textColor="@color/white"
android:textSize="32sp"
android:textStyle="bold" />
- <LinearLayout android:id="@+id/public_key_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="0"
- android:paddingHorizontal="24dp"
- android:paddingVertical="12dp"
- android:orientation="vertical"
- android:background="?android:attr/selectableItemBackground"
- android:clickable="true">
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="9dp"
- android:text="@string/public_key"
- android:textColor="@color/white60"
- android:textSize="13sp"
- android:textStyle="bold" />
- <FrameLayout android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/wireguard_public_key"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/white"
- android:textSize="16sp"
- android:textStyle="bold" />
- <ProgressBar android:id="@+id/public_key_spinner"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:indeterminate="true"
- android:indeterminateOnly="true"
- android:indeterminateDuration="600"
- android:indeterminateDrawable="@drawable/icon_spinner"
- android:visibility="gone" />
- </FrameLayout>
- </LinearLayout>
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingHorizontal="24dp"
- android:paddingVertical="12dp"
- android:orientation="vertical">
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="9dp"
- android:textColor="@color/white60"
- android:textSize="13sp"
- android:textStyle="bold"
- android:text="@string/wireguard_key_generated" />
- <FrameLayout android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/time_since"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/white"
- android:textSize="16sp"
- android:textStyle="bold" />
- <ProgressBar android:id="@+id/time_since_spinner"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:indeterminate="true"
- android:indeterminateOnly="true"
- android:indeterminateDuration="600"
- android:indeterminateDrawable="@drawable/icon_spinner"
- android:visibility="gone" />
- </FrameLayout>
- </LinearLayout>
+ <net.mullvad.mullvadvpn.ui.CopyableInformationView android:id="@+id/public_key"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingHorizontal="24dp"
+ android:paddingVertical="12dp"
+ mullvad:clipboardLabel="@string/wireguard_public_key"
+ mullvad:copiedToast="@string/copied_wireguard_public_key"
+ mullvad:description="@string/public_key"
+ mullvad:whenMissing="showSpinner"/>
+ <net.mullvad.mullvadvpn.ui.InformationView android:id="@+id/key_age"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingHorizontal="24dp"
+ android:paddingVertical="12dp"
+ mullvad:description="@string/wireguard_key_generated"
+ mullvad:whenMissing="showSpinner"/>
<FrameLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"