diff --git a/vector/src/main/java/im/vector/riotredesign/core/files/FileSaver.kt b/vector/src/main/java/im/vector/riotredesign/core/files/FileSaver.kt index e855d3b2..faefe014 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/files/FileSaver.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/files/FileSaver.kt @@ -18,16 +18,18 @@ package im.vector.riotredesign.core.files import android.app.DownloadManager import android.content.Context +import androidx.annotation.WorkerThread +import arrow.core.Try import okio.Okio import timber.log.Timber import java.io.File /** * Save a string to a file with Okio - * @return true in case of success */ -fun saveStringToFile(str: String, file: File): Boolean { - return try { +@WorkerThread +fun writeToFile(str: String, file: File): Try { + return Try { val sink = Okio.sink(file) val bufferedSink = Okio.buffer(sink) @@ -36,14 +38,25 @@ fun saveStringToFile(str: String, file: File): Boolean { bufferedSink.close() sink.close() - - true - } catch (e: Exception) { - Timber.e(e, "Error saving file") - false } } +/** + * Save a byte array to a file with Okio + */ +@WorkerThread +fun writeToFile(data: ByteArray, file: File): Try { + return Try { + val sink = Okio.sink(file) + + val bufferedSink = Okio.buffer(sink) + + bufferedSink.write(data) + + bufferedSink.close() + sink.close() + } +} fun addEntryToDownloadManager(context: Context, file: File, diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keys/KeysExporter.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keys/KeysExporter.kt index 73eee654..6527c263 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keys/KeysExporter.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keys/KeysExporter.kt @@ -18,17 +18,16 @@ package im.vector.riotredesign.features.crypto.keys import android.content.Context import android.os.Environment -import androidx.annotation.WorkerThread import arrow.core.Try import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.extensions.foldToCallback import im.vector.riotredesign.core.files.addEntryToDownloadManager +import im.vector.riotredesign.core.files.writeToFile import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import okio.Okio import java.io.File class KeysExporter(private val session: Session) { @@ -42,7 +41,16 @@ class KeysExporter(private val session: Session) { override fun onSuccess(data: ByteArray) { GlobalScope.launch(Dispatchers.Main) { withContext(Dispatchers.IO) { - copyToFile(context, data) + Try { + val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + val file = File(parentDir, "riotx-keys-" + System.currentTimeMillis() + ".txt") + + writeToFile(data, file) + + addEntryToDownloadManager(context, file, "text/plain") + + file.absolutePath + } } .foldToCallback(callback) } @@ -53,25 +61,4 @@ class KeysExporter(private val session: Session) { } }) } - - @WorkerThread - private fun copyToFile(context: Context, data: ByteArray): Try { - return Try { - val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - val file = File(parentDir, "riotx-keys-" + System.currentTimeMillis() + ".txt") - - val sink = Okio.sink(file) - - val bufferedSink = Okio.buffer(sink) - - bufferedSink.write(data) - - bufferedSink.close() - sink.close() - - addEntryToDownloadManager(context, file, "text/plain") - - file.absolutePath - } - } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt index a951b4c1..2a18a9d6 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt @@ -25,15 +25,20 @@ import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders +import arrow.core.Try import butterknife.BindView import butterknife.OnClick import com.google.android.material.bottomsheet.BottomSheetDialog import im.vector.fragments.keysbackup.setup.KeysBackupSetupSharedViewModel import im.vector.riotredesign.R import im.vector.riotredesign.core.files.addEntryToDownloadManager -import im.vector.riotredesign.core.files.saveStringToFile +import im.vector.riotredesign.core.files.writeToFile import im.vector.riotredesign.core.platform.VectorBaseFragment import im.vector.riotredesign.core.utils.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.File class KeysBackupSetupStep3Fragment : VectorBaseFragment() { @@ -157,30 +162,39 @@ class KeysBackupSetupStep3Fragment : VectorBaseFragment() { } private fun exportRecoveryKeyToFile(data: String) { - val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - val file = File(parentDir, "recovery-key-" + System.currentTimeMillis() + ".txt") + GlobalScope.launch(Dispatchers.Main) { + withContext(Dispatchers.IO) { + Try { + val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + val file = File(parentDir, "recovery-key-" + System.currentTimeMillis() + ".txt") - if (saveStringToFile(data, file)) { - addEntryToDownloadManager(requireContext(), file, "text/plain") + writeToFile(data, file) - context?.let { - AlertDialog.Builder(it) - .setMessage(getString(R.string.recovery_key_export_saved_as_warning, file.absolutePath)) - .setCancelable(false) - .setPositiveButton(R.string.ok, null) - .show() + addEntryToDownloadManager(requireContext(), file, "text/plain") + + file.absolutePath + } } + .fold( + { throwable -> + context?.let { + AlertDialog.Builder(it) + .setTitle(R.string.dialog_title_error) + .setMessage(throwable.localizedMessage) + } + }, + { path -> + viewModel.copyHasBeenMade = true - viewModel.copyHasBeenMade = true - } else { - context?.let { - AlertDialog.Builder(it) - .setTitle(R.string.dialog_title_error) - .setMessage(getString(R.string.unknown_error)) - .setCancelable(false) - .setPositiveButton(R.string.ok, null) - .show() - } + context?.let { + AlertDialog.Builder(it) + .setMessage(getString(R.string.recovery_key_export_saved_as_warning, path)) + } + } + ) + ?.setCancelable(false) + ?.setPositiveButton(R.string.ok, null) + ?.show() } }