forked from hardcoresushi/DroidFS
Safe volume directory picking
This commit is contained in:
parent
fcd382ca8b
commit
9f8b653cc7
@ -1,7 +1,6 @@
|
||||
package sushi.hardcore.droidfs
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
@ -14,15 +13,14 @@ import kotlinx.android.synthetic.main.activity_change_password.*
|
||||
import kotlinx.android.synthetic.main.checkboxes_section.*
|
||||
import kotlinx.android.synthetic.main.volume_path_section.*
|
||||
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class ChangePasswordActivity : VolumeActionActivity() {
|
||||
companion object {
|
||||
private const val PICK_DIRECTORY_REQUEST_CODE = 1
|
||||
}
|
||||
private lateinit var savedVolumesAdapter: SavedVolumesAdapter
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -80,17 +78,12 @@ class ChangePasswordActivity : VolumeActionActivity() {
|
||||
}
|
||||
|
||||
fun pickDirectory(view: View?) {
|
||||
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
|
||||
safePickDirectory()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||
if (data?.data != null) {
|
||||
if (PathUtils.isTreeUriOnPrimaryStorage(data.data!!)){
|
||||
val path = PathUtils.getFullPathFromTreeUri(data.data, this)
|
||||
override fun onDirectoryPicked(uri: Uri) {
|
||||
if (PathUtils.isTreeUriOnPrimaryStorage(uri)){
|
||||
val path = PathUtils.getFullPathFromTreeUri(uri, this)
|
||||
if (path != null){
|
||||
edit_volume_path.setText(path)
|
||||
} else {
|
||||
@ -108,9 +101,6 @@ class ChangePasswordActivity : VolumeActionActivity() {
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickChangePassword(view: View?) {
|
||||
loadVolumePath {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package sushi.hardcore.droidfs
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
@ -11,15 +11,13 @@ import kotlinx.android.synthetic.main.activity_create.*
|
||||
import kotlinx.android.synthetic.main.checkboxes_section.*
|
||||
import kotlinx.android.synthetic.main.volume_path_section.*
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class CreateActivity : VolumeActionActivity() {
|
||||
companion object {
|
||||
private const val PICK_DIRECTORY_REQUEST_CODE = 1
|
||||
}
|
||||
private var sessionID = -1
|
||||
private var isStartingExplorer = false
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -44,17 +42,12 @@ class CreateActivity : VolumeActionActivity() {
|
||||
}
|
||||
|
||||
fun pickDirectory(view: View?) {
|
||||
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
|
||||
safePickDirectory()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||
if (data?.data != null) {
|
||||
if (PathUtils.isTreeUriOnPrimaryStorage(data.data!!)){
|
||||
val path = PathUtils.getFullPathFromTreeUri(data.data, this)
|
||||
override fun onDirectoryPicked(uri: Uri) {
|
||||
if (PathUtils.isTreeUriOnPrimaryStorage(uri)){
|
||||
val path = PathUtils.getFullPathFromTreeUri(uri, this)
|
||||
if (path != null){
|
||||
edit_volume_path.setText(path)
|
||||
} else {
|
||||
@ -72,9 +65,6 @@ class CreateActivity : VolumeActionActivity() {
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickCreate(view: View?) {
|
||||
loadVolumePath {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package sushi.hardcore.droidfs
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
@ -14,23 +14,23 @@ import kotlinx.android.synthetic.main.activity_open.*
|
||||
import kotlinx.android.synthetic.main.checkboxes_section.*
|
||||
import kotlinx.android.synthetic.main.volume_path_section.*
|
||||
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
|
||||
import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivity
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivityDrop
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
|
||||
import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider
|
||||
import sushi.hardcore.droidfs.util.*
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.util.Wiper
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class OpenActivity : VolumeActionActivity() {
|
||||
companion object {
|
||||
private const val PICK_DIRECTORY_REQUEST_CODE = 1
|
||||
}
|
||||
private lateinit var savedVolumesAdapter: SavedVolumesAdapter
|
||||
private var sessionID = -1
|
||||
private var isStartingActivity = false
|
||||
private var isFinishingIntentionally = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_open)
|
||||
@ -107,17 +107,12 @@ class OpenActivity : VolumeActionActivity() {
|
||||
}
|
||||
|
||||
fun pickDirectory(view: View?) {
|
||||
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
isStartingActivity = true
|
||||
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
|
||||
safePickDirectory()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||
if (data?.data != null) {
|
||||
val path = PathUtils.getFullPathFromTreeUri(data.data, this)
|
||||
override fun onDirectoryPicked(uri: Uri) {
|
||||
val path = PathUtils.getFullPathFromTreeUri(uri, this)
|
||||
if (path != null){
|
||||
edit_volume_path.setText(path)
|
||||
} else {
|
||||
@ -128,9 +123,6 @@ class OpenActivity : VolumeActionActivity() {
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickOpen(view: View?) {
|
||||
loadVolumePath {
|
||||
|
@ -1,7 +1,9 @@
|
||||
package sushi.hardcore.droidfs
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.security.keystore.KeyGenParameterSpec
|
||||
import android.security.keystore.KeyPermanentlyInvalidatedException
|
||||
@ -9,6 +11,7 @@ import android.security.keystore.KeyProperties
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricPrompt
|
||||
@ -23,10 +26,15 @@ import java.security.KeyStore
|
||||
import javax.crypto.*
|
||||
import javax.crypto.spec.GCMParameterSpec
|
||||
|
||||
open class VolumeActionActivity : BaseActivity() {
|
||||
abstract class VolumeActionActivity : BaseActivity() {
|
||||
protected lateinit var currentVolumeName: String
|
||||
protected lateinit var currentVolumePath: String
|
||||
protected lateinit var volumeDatabase: VolumeDatabase
|
||||
protected val pickDirectory = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
|
||||
if (uri != null) {
|
||||
onDirectoryPicked(uri)
|
||||
}
|
||||
}
|
||||
private var usf_fingerprint = false
|
||||
private var biometricCanAuthenticateCode: Int = -1
|
||||
private lateinit var biometricManager: BiometricManager
|
||||
@ -48,6 +56,20 @@ open class VolumeActionActivity : BaseActivity() {
|
||||
private const val GCM_TAG_LEN = 128
|
||||
}
|
||||
|
||||
protected abstract fun onDirectoryPicked(uri: Uri)
|
||||
|
||||
protected fun safePickDirectory() {
|
||||
try {
|
||||
pickDirectory.launch(null)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.open_tree_failed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun setupFingerprintStuff(){
|
||||
originalHiddenVolumeSectionLayoutParams = hidden_volume_section.layoutParams as LinearLayout.LayoutParams
|
||||
originalNormalVolumeSectionLayoutParams = normal_volume_section.layoutParams as LinearLayout.LayoutParams
|
||||
@ -137,7 +159,7 @@ open class VolumeActionActivity : BaseActivity() {
|
||||
return if (!keyguardManager.isKeyguardSecure) {
|
||||
1
|
||||
} else {
|
||||
when (biometricManager.canAuthenticate()){
|
||||
when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)){
|
||||
BiometricManager.BIOMETRIC_SUCCESS -> 0
|
||||
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> 2
|
||||
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> 3
|
||||
@ -209,7 +231,7 @@ open class VolumeActionActivity : BaseActivity() {
|
||||
.setSubtitle(getString(R.string.encrypt_action_description))
|
||||
.setDescription(getString(R.string.fingerprint_instruction))
|
||||
.setNegativeButtonText(getString(R.string.cancel))
|
||||
.setDeviceCredentialAllowed(false)
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
||||
.setConfirmationRequired(false)
|
||||
.build()
|
||||
if (!isCipherReady){
|
||||
@ -233,7 +255,7 @@ open class VolumeActionActivity : BaseActivity() {
|
||||
.setSubtitle(getString(R.string.decrypt_action_description))
|
||||
.setDescription(getString(R.string.fingerprint_instruction))
|
||||
.setNegativeButtonText(getString(R.string.cancel))
|
||||
.setDeviceCredentialAllowed(false)
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
||||
.setConfirmationRequired(false)
|
||||
.build()
|
||||
this.onPasswordDecrypted = onPasswordDecrypted
|
||||
|
@ -2,35 +2,148 @@ package sushi.hardcore.droidfs.explorers
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import sushi.hardcore.droidfs.CameraActivity
|
||||
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.OpenActivity
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.adapters.IconTextDialogAdapter
|
||||
import sushi.hardcore.droidfs.file_operations.OperationFile
|
||||
import sushi.hardcore.droidfs.content_providers.ExternalProvider
|
||||
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.file_operations.OperationFile
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import java.io.File
|
||||
|
||||
class ExplorerActivity : BaseExplorerActivity() {
|
||||
companion object {
|
||||
private const val PICK_DIRECTORY_REQUEST_CODE = 1
|
||||
private const val PICK_FILES_REQUEST_CODE = 2
|
||||
private const val PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE = 3
|
||||
private enum class ItemsActions {NONE, COPY, MOVE}
|
||||
}
|
||||
private var usf_decrypt = false
|
||||
private var usf_share = false
|
||||
private var currentItemAction = ItemsActions.NONE
|
||||
private val itemsToProcess = ArrayList<OperationFile>()
|
||||
private val pickFromOtherVolumes = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
result.data?.let { resultIntent ->
|
||||
val remoteSessionID = resultIntent.getIntExtra("sessionID", -1)
|
||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||
val path = resultIntent.getStringExtra("path")
|
||||
val operationFiles = ArrayList<OperationFile>()
|
||||
if (path == null){ //multiples elements
|
||||
val paths = resultIntent.getStringArrayListExtra("paths")
|
||||
val types = resultIntent.getIntegerArrayListExtra("types")
|
||||
if (types != null && paths != null){
|
||||
for (i in paths.indices) {
|
||||
operationFiles.add(
|
||||
OperationFile.fromExplorerElement(
|
||||
ExplorerElement(File(paths[i]).name, types[i].toShort(), -1, -1, PathUtils.getParentPath(paths[i]))
|
||||
)
|
||||
)
|
||||
if (types[i] == 0){ //directory
|
||||
remoteGocryptfsVolume.recursiveMapFiles(paths[i]).forEach {
|
||||
operationFiles.add(OperationFile.fromExplorerElement(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
operationFiles.add(
|
||||
OperationFile.fromExplorerElement(
|
||||
ExplorerElement(File(path).name, 1, -1, -1, PathUtils.getParentPath(path))
|
||||
)
|
||||
)
|
||||
}
|
||||
if (operationFiles.size > 0){
|
||||
checkPathOverwrite(operationFiles, currentDirectoryPath) { items ->
|
||||
if (items == null) {
|
||||
remoteGocryptfsVolume.close()
|
||||
} else {
|
||||
fileOperationService.copyElements(items, remoteGocryptfsVolume){ failedItem ->
|
||||
runOnUiThread {
|
||||
if (failedItem == null){
|
||||
Toast.makeText(this, R.string.success_import, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
remoteGocryptfsVolume.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
remoteGocryptfsVolume.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private val pickFiles = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { uris ->
|
||||
if (uris != null) {
|
||||
importFilesFromUris(uris){ failedItem ->
|
||||
if (failedItem == null){
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage("""
|
||||
${getString(R.string.success_import_msg)}
|
||||
${getString(R.string.ask_for_wipe)}
|
||||
""".trimIndent())
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
fileOperationService.wipeUris(uris) { errorMsg ->
|
||||
runOnUiThread {
|
||||
if (errorMsg == null){
|
||||
Toast.makeText(this, R.string.wipe_successful, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
private val pickDirectory = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
|
||||
if (uri != null) {
|
||||
fileOperationService.exportFiles(uri, explorerAdapter.selectedItems.map { i -> explorerElements[i] }){ failedItem ->
|
||||
runOnUiThread {
|
||||
if (failedItem == null){
|
||||
Toast.makeText(this, R.string.success_export, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.export_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unselectAll()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
setContentView(R.layout.activity_explorer)
|
||||
usf_decrypt = sharedPrefs.getBoolean("usf_decrypt", false)
|
||||
@ -82,15 +195,11 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
intent.action = "pick"
|
||||
intent.putExtra("sessionID", gocryptfsVolume.sessionID)
|
||||
isStartingActivity = true
|
||||
startActivityForResult(intent, PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE)
|
||||
pickFromOtherVolumes.launch(intent)
|
||||
}
|
||||
"importFiles" -> {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||
intent.type = "*/*"
|
||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
isStartingActivity = true
|
||||
startActivityForResult(intent, PICK_FILES_REQUEST_CODE)
|
||||
pickFiles.launch(arrayOf("*/*"))
|
||||
}
|
||||
"createFile" -> {
|
||||
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
|
||||
@ -132,136 +241,6 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == PICK_FILES_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val uris: MutableList<Uri> = ArrayList()
|
||||
val singleUri = data.data
|
||||
if (singleUri == null) { //multiples choices
|
||||
val clipData = data.clipData
|
||||
if (clipData != null){
|
||||
for (i in 0 until clipData.itemCount) {
|
||||
uris.add(clipData.getItemAt(i).uri)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uris.add(singleUri)
|
||||
}
|
||||
importFilesFromUris(uris){ failedItem ->
|
||||
if (failedItem == null){
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.success_import)
|
||||
.setMessage("""
|
||||
${getString(R.string.success_import_msg)}
|
||||
${getString(R.string.ask_for_wipe)}
|
||||
""".trimIndent())
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
fileOperationService.wipeUris(uris) { errorMsg ->
|
||||
runOnUiThread {
|
||||
if (errorMsg == null){
|
||||
Toast.makeText(this, R.string.wipe_successful, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
data.data?.let { uri ->
|
||||
fileOperationService.exportFiles(uri, explorerAdapter.selectedItems.map { i -> explorerElements[i] }){ failedItem ->
|
||||
runOnUiThread {
|
||||
if (failedItem == null){
|
||||
Toast.makeText(this, R.string.success_export, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.export_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
unselectAll()
|
||||
}
|
||||
}
|
||||
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val remoteSessionID = data.getIntExtra("sessionID", -1)
|
||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
||||
val path = data.getStringExtra("path")
|
||||
val operationFiles = ArrayList<OperationFile>()
|
||||
if (path == null){ //multiples elements
|
||||
val paths = data.getStringArrayListExtra("paths")
|
||||
val types = data.getIntegerArrayListExtra("types")
|
||||
if (types != null && paths != null){
|
||||
for (i in paths.indices) {
|
||||
operationFiles.add(
|
||||
OperationFile.fromExplorerElement(
|
||||
ExplorerElement(File(paths[i]).name, types[i].toShort(), -1, -1, PathUtils.getParentPath(paths[i]))
|
||||
)
|
||||
)
|
||||
if (types[i] == 0){ //directory
|
||||
remoteGocryptfsVolume.recursiveMapFiles(paths[i]).forEach {
|
||||
operationFiles.add(OperationFile.fromExplorerElement(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
operationFiles.add(
|
||||
OperationFile.fromExplorerElement(
|
||||
ExplorerElement(File(path).name, 1, -1, -1, PathUtils.getParentPath(path))
|
||||
)
|
||||
)
|
||||
}
|
||||
if (operationFiles.size > 0){
|
||||
checkPathOverwrite(operationFiles, currentDirectoryPath) { items ->
|
||||
if (items == null) {
|
||||
remoteGocryptfsVolume.close()
|
||||
} else {
|
||||
fileOperationService.copyElements(items, remoteGocryptfsVolume){ failedItem ->
|
||||
runOnUiThread {
|
||||
if (failedItem == null){
|
||||
Toast.makeText(this, R.string.success_import, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(getString(R.string.import_failed, failedItem))
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
setCurrentPath(currentDirectoryPath)
|
||||
}
|
||||
remoteGocryptfsVolume.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
remoteGocryptfsVolume.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.explorer, menu)
|
||||
if (currentItemAction != ItemsActions.NONE) {
|
||||
@ -398,9 +377,8 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
true
|
||||
}
|
||||
R.id.decrypt -> {
|
||||
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
isStartingActivity = true
|
||||
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
|
||||
pickDirectory.launch(null)
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
|
@ -194,4 +194,5 @@
|
||||
<string name="folders_first_summary">Show folders at the beginning of the list</string>
|
||||
<string name="auto_fit_title">Video player screen auto-rotation</string>
|
||||
<string name="auto_fit_summary">Auto-rotate the screen to fit video dimensions</string>
|
||||
<string name="open_tree_failed">No file explorer found. Please install one and retry.</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user