aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-03-19 17:54:32 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2020-03-19 18:55:45 -0600
commit8451321a790d38f3a6932edc852cdda5c8469df9 (patch)
tree0f30e28b1ca9c7c458e56eb5817a8b042b566f6e /ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt
parentTunnelListFragment: cleanup list type (diff)
downloadwireguard-android-8451321a790d38f3a6932edc852cdda5c8469df9.tar.xz
wireguard-android-8451321a790d38f3a6932edc852cdda5c8469df9.zip
preferences: rewrite in kotlin
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt98
1 files changed, 98 insertions, 0 deletions
diff --git a/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt
new file mode 100644
index 00000000..2a77f36c
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package com.wireguard.android.preference
+
+import android.Manifest
+import android.content.Context
+import android.content.pm.PackageManager
+import android.util.AttributeSet
+import android.util.Log
+import androidx.preference.Preference
+import com.google.android.material.snackbar.Snackbar
+import com.wireguard.android.Application
+import com.wireguard.android.R
+import com.wireguard.android.model.ObservableTunnel
+import com.wireguard.android.util.DownloadsFileSaver
+import com.wireguard.android.util.ErrorMessages
+import com.wireguard.android.util.FragmentUtils
+import com.wireguard.android.util.ObservableSortedKeyedList
+import com.wireguard.config.Config
+import java9.util.concurrent.CompletableFuture
+import java.nio.charset.StandardCharsets
+import java.util.ArrayList
+import java.util.zip.ZipEntry
+import java.util.zip.ZipOutputStream
+
+/**
+ * Preference implementing a button that asynchronously exports config zips.
+ */
+class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
+ private var exportedFilePath: String? = null
+
+ private fun exportZip() {
+ Application.getTunnelManager().tunnels.thenAccept(this::exportZip)
+ }
+
+ private fun exportZip(tunnels: List<ObservableTunnel>) {
+ val futureConfigs = tunnels.map { it.configAsync.toCompletableFuture() }.toTypedArray()
+ if (futureConfigs.isEmpty()) {
+ exportZipComplete(null, IllegalArgumentException(
+ context.getString(R.string.no_tunnels_error)))
+ return
+ }
+ CompletableFuture.allOf(*futureConfigs)
+ .whenComplete { _, exception ->
+ Application.getAsyncWorker().supplyAsync {
+ if (exception != null) throw exception
+ val outputFile = DownloadsFileSaver.save(context, "wireguard-export.zip", "application/zip", true)
+ try {
+ ZipOutputStream(outputFile.outputStream).use { zip ->
+ for (i in futureConfigs.indices) {
+ zip.putNextEntry(ZipEntry(tunnels[i].name + ".conf"))
+ zip.write(futureConfigs[i].getNow(null)!!.toWgQuickString().toByteArray(StandardCharsets.UTF_8))
+ }
+ zip.closeEntry()
+ }
+ } catch (e: Exception) {
+ outputFile.delete()
+ throw e
+ }
+ outputFile.fileName
+ }.whenComplete(this::exportZipComplete)
+ }
+ }
+
+ private fun exportZipComplete(filePath: String?, throwable: Throwable?) {
+ if (throwable != null) {
+ val error = ErrorMessages.get(throwable)
+ val message = context.getString(R.string.zip_export_error, error)
+ Log.e(TAG, message, throwable)
+ Snackbar.make(
+ FragmentUtils.getPrefActivity(this).findViewById(android.R.id.content),
+ message, Snackbar.LENGTH_LONG).show()
+ isEnabled = true
+ } else {
+ exportedFilePath = filePath
+ notifyChanged()
+ }
+ }
+
+ override fun getSummary() = if (exportedFilePath == null) context.getString(R.string.zip_export_summary) else context.getString(R.string.zip_export_success, exportedFilePath)
+
+ override fun getTitle() = context.getString(R.string.zip_export_title)
+
+ override fun onClick() {
+ FragmentUtils.getPrefActivity(this).ensurePermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { _, granted ->
+ if (granted.isNotEmpty() && granted[0] == PackageManager.PERMISSION_GRANTED) {
+ isEnabled = false
+ exportZip()
+ }
+ }
+ }
+
+ companion object {
+ private val TAG = "WireGuard/" + ZipExporterPreference::class.java.simpleName
+ }
+}