2020-07-17 16:35:39 +02:00
|
|
|
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
|
2020-07-19 21:46:29 +02:00
|
|
|
import android.view.WindowManager
|
|
|
|
import android.widget.EditText
|
|
|
|
import android.widget.Toast
|
2020-07-28 22:25:10 +02:00
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
2020-08-01 15:39:00 +02:00
|
|
|
import com.github.clans.fab.FloatingActionButton
|
2020-07-19 21:46:29 +02:00
|
|
|
import com.github.clans.fab.FloatingActionMenu
|
2020-07-17 16:35:39 +02:00
|
|
|
import kotlinx.android.synthetic.main.activity_explorer.*
|
|
|
|
import sushi.hardcore.droidfs.OpenActivity
|
|
|
|
import sushi.hardcore.droidfs.R
|
2020-07-28 22:25:10 +02:00
|
|
|
import sushi.hardcore.droidfs.util.*
|
2020-07-27 16:20:52 +02:00
|
|
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
2020-07-17 16:35:39 +02:00
|
|
|
import java.io.File
|
2020-08-01 15:39:00 +02:00
|
|
|
import kotlin.collections.ArrayList
|
2020-07-17 16:35:39 +02:00
|
|
|
|
2020-07-19 21:46:29 +02:00
|
|
|
class ExplorerActivity : BaseExplorerActivity() {
|
2020-07-17 16:35:39 +02:00
|
|
|
private val PICK_DIRECTORY_REQUEST_CODE = 1
|
|
|
|
private val PICK_FILES_REQUEST_CODE = 2
|
|
|
|
private val PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE = 3
|
|
|
|
private var usf_decrypt = false
|
|
|
|
private var usf_share = false
|
2020-08-01 15:39:00 +02:00
|
|
|
private var modeSelectLocation = false
|
|
|
|
private val filesToCopy = ArrayList<ExplorerElement>()
|
2020-07-17 16:35:39 +02:00
|
|
|
override fun init() {
|
|
|
|
setContentView(R.layout.activity_explorer)
|
|
|
|
usf_decrypt = sharedPrefs.getBoolean("usf_decrypt", false)
|
|
|
|
usf_share = sharedPrefs.getBoolean("usf_share", false)
|
|
|
|
}
|
|
|
|
|
2020-08-01 15:39:00 +02:00
|
|
|
override fun onExplorerItemLongClick(position: Int) {
|
|
|
|
cancelCopy()
|
|
|
|
explorerAdapter.onItemLongClick(position)
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
|
2020-07-19 21:46:29 +02:00
|
|
|
private fun createNewFile(fileName: String){
|
|
|
|
if (fileName.isEmpty()) {
|
|
|
|
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
|
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
val handleID = gocryptfsVolume.openWriteMode(PathUtils.path_join(currentDirectoryPath, fileName))
|
2020-07-19 21:46:29 +02:00
|
|
|
if (handleID == -1) {
|
2020-07-27 16:20:52 +02:00
|
|
|
ColoredAlertDialogBuilder(this)
|
2020-07-19 21:46:29 +02:00
|
|
|
.setTitle(R.string.error)
|
2020-07-26 21:16:06 +02:00
|
|
|
.setMessage(R.string.file_creation_failed)
|
2020-07-19 21:46:29 +02:00
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
gocryptfsVolume.closeFile(handleID)
|
2020-07-26 21:16:06 +02:00
|
|
|
setCurrentPath(currentDirectoryPath)
|
2020-07-19 21:46:29 +02:00
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onClickCreateFile(view: View) {
|
|
|
|
findViewById<FloatingActionMenu>(R.id.fam_explorer).close(true)
|
|
|
|
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
|
|
|
|
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
|
2020-07-27 16:20:52 +02:00
|
|
|
val dialog = ColoredAlertDialogBuilder(this)
|
2020-07-19 21:46:29 +02:00
|
|
|
.setView(dialogEditTextView)
|
|
|
|
.setTitle(getString(R.string.enter_file_name))
|
|
|
|
.setPositiveButton(R.string.ok) { _, _ ->
|
|
|
|
val fileName = dialogEditText.text.toString()
|
|
|
|
createNewFile(fileName)
|
|
|
|
}
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.create()
|
|
|
|
dialogEditText.setOnEditorActionListener { _, _, _ ->
|
|
|
|
val fileName = dialogEditText.text.toString()
|
|
|
|
dialog.dismiss()
|
|
|
|
createNewFile(fileName)
|
|
|
|
true
|
|
|
|
}
|
|
|
|
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
|
|
|
dialog.show()
|
|
|
|
}
|
|
|
|
|
2020-07-17 16:35:39 +02:00
|
|
|
fun onClickAddFile(view: View?) {
|
|
|
|
fam_explorer.close(true)
|
2020-07-28 22:25:10 +02:00
|
|
|
val i = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
2020-07-17 16:35:39 +02:00
|
|
|
i.type = "*/*"
|
|
|
|
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
|
|
|
i.addCategory(Intent.CATEGORY_OPENABLE)
|
|
|
|
startActivityForResult(i, PICK_FILES_REQUEST_CODE)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onClickAddFileFromOtherVolume(view: View?) {
|
|
|
|
fam_explorer.close(true)
|
|
|
|
val intent = Intent(this, OpenActivity::class.java)
|
|
|
|
intent.action = "pick"
|
|
|
|
startActivityForResult(intent, PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE)
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2020-07-28 22:25:10 +02:00
|
|
|
object : LoadingTask(this, R.string.loading_msg_import){
|
|
|
|
override fun doTask(activity: AppCompatActivity) {
|
|
|
|
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)
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
var success = true
|
|
|
|
for (uri in uris) {
|
|
|
|
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri))
|
|
|
|
contentResolver.openInputStream(uri)?.let {
|
2020-08-01 16:43:48 +02:00
|
|
|
success = gocryptfsVolume.importFile(it, dstPath)
|
2020-07-28 22:25:10 +02:00
|
|
|
}
|
|
|
|
if (!success) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.import_failed, uri))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
if (success) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.success_import)
|
|
|
|
.setMessage("""
|
|
|
|
${getString(R.string.success_import_msg)}
|
|
|
|
${getString(R.string.ask_for_wipe)}
|
|
|
|
""".trimIndent())
|
|
|
|
.setPositiveButton(R.string.yes) { _, _ ->
|
|
|
|
object : LoadingTask(activity, R.string.loading_msg_wipe){
|
|
|
|
override fun doTask(activity: AppCompatActivity) {
|
|
|
|
success = true
|
|
|
|
for (uri in uris) {
|
|
|
|
val errorMsg = Wiper.wipe(activity, uri)
|
|
|
|
if (errorMsg != null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.wipe_failed, errorMsg))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
success = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (success) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.wipe_successful)
|
|
|
|
.setMessage(R.string.wipe_success_msg)
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.setNegativeButton(getString(R.string.no), null)
|
2020-07-17 16:35:39 +02:00
|
|
|
.show()
|
2020-07-28 22:25:10 +02:00
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
override fun doFinally(activity: AppCompatActivity){
|
|
|
|
setCurrentPath(currentDirectoryPath)
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
|
|
|
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
2020-07-28 22:25:10 +02:00
|
|
|
object : LoadingTask(this, R.string.loading_msg_export){
|
|
|
|
override fun doTask(activity: AppCompatActivity) {
|
|
|
|
val uri = data.data
|
|
|
|
val outputDir = PathUtils.getFullPathFromTreeUri(uri, activity)
|
|
|
|
var failedItem: String? = null
|
|
|
|
for (i in explorerAdapter.selectedItems) {
|
|
|
|
val element = explorerAdapter.getItem(i)
|
|
|
|
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
|
|
|
failedItem = if (element.isDirectory) {
|
|
|
|
recursiveExportDirectory(fullPath, outputDir)
|
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
if (gocryptfsVolume.exportFile(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
|
2020-07-28 22:25:10 +02:00
|
|
|
}
|
|
|
|
if (failedItem != null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.export_failed, failedItem))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (failedItem == null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.success_export)
|
|
|
|
.setMessage(R.string.success_export_msg)
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
override fun doFinally(activity: AppCompatActivity) {
|
|
|
|
unselectAll()
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
|
|
|
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
2020-07-28 22:25:10 +02:00
|
|
|
object : LoadingTask(this, R.string.loading_msg_import){
|
|
|
|
override fun doTask(activity: AppCompatActivity) {
|
|
|
|
val remoteSessionID = data.getIntExtra("sessionID", -1)
|
|
|
|
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
|
|
|
val path = data.getStringExtra("path")
|
|
|
|
var failedItem: String? = null
|
|
|
|
if (path == null) {
|
|
|
|
val paths = data.getStringArrayListExtra("paths")
|
|
|
|
val types = data.getIntegerArrayListExtra("types")
|
|
|
|
if (types != null && paths != null){
|
|
|
|
for (i in paths.indices) {
|
|
|
|
failedItem = if (types[i] == 0) { //directory
|
|
|
|
recursiveImportDirectoryFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)
|
|
|
|
} else {
|
2020-08-01 15:39:00 +02:00
|
|
|
if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], PathUtils.path_join(currentDirectoryPath, File(paths[i]).name))) null else paths[i]
|
2020-07-28 22:25:10 +02:00
|
|
|
}
|
|
|
|
if (failedItem != null) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
} else {
|
2020-08-01 15:39:00 +02:00
|
|
|
failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, PathUtils.path_join(currentDirectoryPath, File(path).name))) null else path
|
2020-07-28 22:25:10 +02:00
|
|
|
}
|
|
|
|
if (failedItem == null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.success_import)
|
|
|
|
.setMessage(R.string.success_import_msg)
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.import_failed, failedItem))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
remoteGocryptfsVolume.close()
|
|
|
|
}
|
|
|
|
override fun doFinally(activity: AppCompatActivity) {
|
|
|
|
setCurrentPath(currentDirectoryPath)
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
|
|
menuInflater.inflate(R.menu.explorer, menu)
|
2020-08-01 15:39:00 +02:00
|
|
|
if (modeSelectLocation) {
|
|
|
|
menu.findItem(R.id.validate).isVisible = true
|
|
|
|
menu.findItem(R.id.close).isVisible = false
|
|
|
|
} else {
|
|
|
|
handleMenuItems(menu)
|
|
|
|
if (usf_share){
|
|
|
|
menu.findItem(R.id.share).isVisible = false
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-08-01 15:39:00 +02:00
|
|
|
val anyItemSelected = explorerAdapter.selectedItems.isNotEmpty()
|
|
|
|
menu.findItem(R.id.select_all).isVisible = anyItemSelected
|
|
|
|
menu.findItem(R.id.delete).isVisible = anyItemSelected
|
|
|
|
menu.findItem(R.id.copy).isVisible = anyItemSelected
|
|
|
|
menu.findItem(R.id.decrypt).isVisible = anyItemSelected && usf_decrypt
|
|
|
|
if (anyItemSelected && usf_share){
|
|
|
|
var containsDir = false
|
|
|
|
for (i in explorerAdapter.selectedItems) {
|
|
|
|
if (explorerElements[i].isDirectory) {
|
|
|
|
containsDir = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!containsDir) {
|
|
|
|
menu.findItem(R.id.share).isVisible = true
|
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
return when (item.itemId) {
|
2020-08-01 15:39:00 +02:00
|
|
|
android.R.id.home -> {
|
|
|
|
cancelCopy()
|
|
|
|
super.onOptionsItemSelected(item)
|
|
|
|
}
|
|
|
|
R.id.select_all -> {
|
2020-07-26 21:16:06 +02:00
|
|
|
explorerAdapter.selectAll()
|
2020-07-17 16:35:39 +02:00
|
|
|
invalidateOptionsMenu()
|
|
|
|
true
|
|
|
|
}
|
2020-08-01 15:39:00 +02:00
|
|
|
R.id.copy -> {
|
|
|
|
for (i in explorerAdapter.selectedItems){
|
|
|
|
filesToCopy.add(explorerElements[i])
|
|
|
|
}
|
|
|
|
modeSelectLocation = true
|
|
|
|
unselectAll()
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_add_file).visibility = View.GONE
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_import_file).visibility = View.GONE
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_import_file_from_other_volume).visibility = View.GONE
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.validate -> {
|
|
|
|
object : LoadingTask(this, R.string.loading_msg_copy){
|
|
|
|
override fun doTask(activity: AppCompatActivity) {
|
|
|
|
var failedItem: String? = null
|
|
|
|
for (element in filesToCopy) {
|
|
|
|
val originalPath = element.getFullPath()
|
|
|
|
failedItem = if (element.isDirectory) {
|
|
|
|
recursiveCopyDirectory(originalPath, currentDirectoryPath)
|
|
|
|
} else {
|
|
|
|
if (copyFile(originalPath, PathUtils.path_join(currentDirectoryPath, element.name))) null else originalPath
|
|
|
|
}
|
|
|
|
if (failedItem != null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.copy_failed, failedItem))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (failedItem == null) {
|
|
|
|
stopTask {
|
|
|
|
ColoredAlertDialogBuilder(activity)
|
|
|
|
.setTitle(getString(R.string.copy_success))
|
|
|
|
.setMessage(getString(R.string.copy_success_msg))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
override fun doFinally(activity: AppCompatActivity) {
|
|
|
|
cancelCopy()
|
|
|
|
unselectAll()
|
|
|
|
setCurrentPath(currentDirectoryPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.delete -> {
|
2020-07-26 21:16:06 +02:00
|
|
|
val size = explorerAdapter.selectedItems.size
|
2020-07-27 16:20:52 +02:00
|
|
|
val dialog = ColoredAlertDialogBuilder(this)
|
2020-07-17 16:35:39 +02:00
|
|
|
dialog.setTitle(R.string.warning)
|
2020-07-26 21:16:06 +02:00
|
|
|
dialog.setPositiveButton(R.string.ok) { _, _ -> removeSelectedItems() }
|
2020-07-17 16:35:39 +02:00
|
|
|
dialog.setNegativeButton(R.string.cancel, null)
|
|
|
|
if (size > 1) {
|
2020-07-26 21:16:06 +02:00
|
|
|
dialog.setMessage(getString(R.string.multiple_delete_confirm, explorerAdapter.selectedItems.size.toString()))
|
2020-07-17 16:35:39 +02:00
|
|
|
} else {
|
2020-07-26 21:16:06 +02:00
|
|
|
dialog.setMessage(getString(R.string.single_delete_confirm, explorerAdapter.getItem(explorerAdapter.selectedItems[0]).name))
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
dialog.show()
|
|
|
|
true
|
|
|
|
}
|
2020-08-01 15:39:00 +02:00
|
|
|
R.id.share -> {
|
2020-07-17 16:35:39 +02:00
|
|
|
val paths: MutableList<String> = ArrayList()
|
2020-07-26 21:16:06 +02:00
|
|
|
for (i in explorerAdapter.selectedItems) {
|
2020-08-01 15:39:00 +02:00
|
|
|
paths.add(explorerElements[i].getFullPath())
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
ExternalProvider.share(this, gocryptfsVolume, paths)
|
2020-07-28 22:25:10 +02:00
|
|
|
unselectAll()
|
2020-07-17 16:35:39 +02:00
|
|
|
true
|
|
|
|
}
|
2020-08-01 15:39:00 +02:00
|
|
|
R.id.decrypt -> {
|
2020-07-17 16:35:39 +02:00
|
|
|
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
|
|
|
startActivityForResult(i, PICK_DIRECTORY_REQUEST_CODE)
|
|
|
|
true
|
|
|
|
}
|
|
|
|
else -> super.onOptionsItemSelected(item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 15:39:00 +02:00
|
|
|
private fun cancelCopy() {
|
|
|
|
if (modeSelectLocation){
|
|
|
|
modeSelectLocation = false
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_add_file).visibility = View.VISIBLE
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_import_file).visibility = View.VISIBLE
|
|
|
|
findViewById<FloatingActionButton>(R.id.fab_import_file_from_other_volume).visibility = View.VISIBLE
|
|
|
|
filesToCopy.clear()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun copyFile(srcPath: String, dstPath: String): Boolean {
|
|
|
|
var success = true
|
2020-08-01 16:43:48 +02:00
|
|
|
val originalHandleId = gocryptfsVolume.openReadMode(srcPath)
|
2020-08-01 15:39:00 +02:00
|
|
|
if (originalHandleId != -1){
|
2020-08-01 16:43:48 +02:00
|
|
|
val newHandleId = gocryptfsVolume.openWriteMode(dstPath)
|
2020-08-01 15:39:00 +02:00
|
|
|
if (newHandleId != -1){
|
|
|
|
var offset: Long = 0
|
|
|
|
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
|
|
|
|
var length: Int
|
2020-08-01 16:43:48 +02:00
|
|
|
while (gocryptfsVolume.readFile(originalHandleId, offset, ioBuffer).also { length = it } > 0) {
|
|
|
|
val written = gocryptfsVolume.writeFile(newHandleId, offset, ioBuffer, length).toLong()
|
2020-08-01 15:39:00 +02:00
|
|
|
if (written == length.toLong()) {
|
|
|
|
offset += written
|
|
|
|
} else {
|
|
|
|
success = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-08-01 16:43:48 +02:00
|
|
|
gocryptfsVolume.closeFile(newHandleId)
|
2020-08-01 15:39:00 +02:00
|
|
|
} else {
|
|
|
|
success = false
|
|
|
|
}
|
2020-08-01 16:43:48 +02:00
|
|
|
gocryptfsVolume.closeFile(originalHandleId)
|
2020-08-01 15:39:00 +02:00
|
|
|
} else {
|
|
|
|
success = false
|
|
|
|
}
|
|
|
|
return success
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun recursiveCopyDirectory(srcDirectoryPath: String, outputPath: String): String? {
|
2020-08-01 16:43:48 +02:00
|
|
|
val mappedElements = gocryptfsVolume.recursiveMapFiles(srcDirectoryPath)
|
2020-08-01 15:39:00 +02:00
|
|
|
val dstDirectoryPath = PathUtils.path_join(outputPath, File(srcDirectoryPath).name)
|
2020-08-01 16:43:48 +02:00
|
|
|
if (!gocryptfsVolume.pathExists(dstDirectoryPath)) {
|
2020-08-01 15:39:00 +02:00
|
|
|
if (!gocryptfsVolume.mkdir(dstDirectoryPath)) {
|
|
|
|
return dstDirectoryPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (e in mappedElements) {
|
|
|
|
val srcPath = e.getFullPath()
|
|
|
|
val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, srcPath))
|
|
|
|
if (e.isDirectory) {
|
|
|
|
if (!gocryptfsVolume.mkdir(dstPath)){
|
|
|
|
return srcPath
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!copyFile(srcPath, dstPath)) {
|
|
|
|
return srcPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, srcPath: String, dstPath: String): Boolean {
|
2020-07-17 16:35:39 +02:00
|
|
|
var success = true
|
2020-08-01 16:43:48 +02:00
|
|
|
val srcHandleID = remote_gocryptfsVolume.openReadMode(srcPath)
|
2020-07-26 21:16:06 +02:00
|
|
|
if (srcHandleID != -1) {
|
2020-08-01 16:43:48 +02:00
|
|
|
val dstHandleID = gocryptfsVolume.openWriteMode(dstPath)
|
2020-07-26 21:16:06 +02:00
|
|
|
if (dstHandleID != -1) {
|
2020-07-17 16:35:39 +02:00
|
|
|
var length: Int
|
2020-07-26 21:16:06 +02:00
|
|
|
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
|
2020-07-17 16:35:39 +02:00
|
|
|
var offset: Long = 0
|
2020-08-01 16:43:48 +02:00
|
|
|
while (remote_gocryptfsVolume.readFile(srcHandleID, offset, ioBuffer).also { length = it } > 0){
|
|
|
|
val written = gocryptfsVolume.writeFile(dstHandleID, offset, ioBuffer, length).toLong()
|
2020-07-17 16:35:39 +02:00
|
|
|
if (written == length.toLong()) {
|
|
|
|
offset += length.toLong()
|
|
|
|
} else {
|
|
|
|
success = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-08-01 16:43:48 +02:00
|
|
|
gocryptfsVolume.closeFile(dstHandleID)
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
2020-08-01 16:43:48 +02:00
|
|
|
remote_gocryptfsVolume.closeFile(srcHandleID)
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
return success
|
|
|
|
}
|
|
|
|
|
2020-08-01 15:39:00 +02:00
|
|
|
private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, outputPath: String): String? {
|
2020-08-01 16:43:48 +02:00
|
|
|
val mappedElements = gocryptfsVolume.recursiveMapFiles(remote_directory_path)
|
2020-08-01 15:39:00 +02:00
|
|
|
val dstDirectoryPath = PathUtils.path_join(outputPath, File(remote_directory_path).name)
|
2020-08-01 16:43:48 +02:00
|
|
|
if (!gocryptfsVolume.pathExists(dstDirectoryPath)) {
|
2020-08-01 15:39:00 +02:00
|
|
|
if (!gocryptfsVolume.mkdir(dstDirectoryPath)) {
|
|
|
|
return dstDirectoryPath
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-01 15:39:00 +02:00
|
|
|
for (e in mappedElements) {
|
|
|
|
val srcPath = e.getFullPath()
|
|
|
|
val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(remote_directory_path, srcPath))
|
2020-07-17 16:35:39 +02:00
|
|
|
if (e.isDirectory) {
|
2020-08-01 15:39:00 +02:00
|
|
|
if (!gocryptfsVolume.mkdir(dstPath)){
|
|
|
|
return srcPath
|
|
|
|
}
|
2020-07-17 16:35:39 +02:00
|
|
|
} else {
|
2020-08-01 15:39:00 +02:00
|
|
|
if (!importFileFromOtherVolume(remote_gocryptfsVolume, srcPath, dstPath)) {
|
|
|
|
return srcPath
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:16:06 +02:00
|
|
|
private fun recursiveExportDirectory(plain_directory_path: String, output_dir: String?): String? {
|
|
|
|
if (File(PathUtils.path_join(output_dir, plain_directory_path)).mkdir()) {
|
2020-08-01 16:43:48 +02:00
|
|
|
val explorerElements = gocryptfsVolume.listDir(plain_directory_path)
|
2020-07-26 21:16:06 +02:00
|
|
|
for (e in explorerElements) {
|
|
|
|
val fullPath = PathUtils.path_join(plain_directory_path, e.name)
|
2020-07-17 16:35:39 +02:00
|
|
|
if (e.isDirectory) {
|
2020-07-26 21:16:06 +02:00
|
|
|
val failedItem = recursiveExportDirectory(fullPath, output_dir)
|
|
|
|
failedItem?.let { return it }
|
2020-07-17 16:35:39 +02:00
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
if (!gocryptfsVolume.exportFile(fullPath, PathUtils.path_join(output_dir, fullPath))) {
|
2020-07-26 21:16:06 +02:00
|
|
|
return fullPath
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
return output_dir
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:16:06 +02:00
|
|
|
private fun recursiveRemoveDirectory(plain_directory_path: String): String? {
|
2020-08-01 16:43:48 +02:00
|
|
|
val explorerElements = gocryptfsVolume.listDir(plain_directory_path)
|
2020-07-26 21:16:06 +02:00
|
|
|
for (e in explorerElements) {
|
|
|
|
val fullPath = PathUtils.path_join(plain_directory_path, e.name)
|
2020-07-17 16:35:39 +02:00
|
|
|
if (e.isDirectory) {
|
2020-07-26 21:16:06 +02:00
|
|
|
val result = recursiveRemoveDirectory(fullPath)
|
2020-07-17 16:35:39 +02:00
|
|
|
result?.let { return it }
|
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
if (!gocryptfsVolume.removeFile(fullPath)) {
|
2020-07-26 21:16:06 +02:00
|
|
|
return fullPath
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return if (!gocryptfsVolume.rmdir(plain_directory_path)) {
|
|
|
|
plain_directory_path
|
|
|
|
} else {
|
|
|
|
null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:16:06 +02:00
|
|
|
private fun removeSelectedItems() {
|
|
|
|
var failedItem: String? = null
|
|
|
|
for (i in explorerAdapter.selectedItems) {
|
|
|
|
val element = explorerAdapter.getItem(i)
|
|
|
|
val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
|
2020-07-17 16:35:39 +02:00
|
|
|
if (element.isDirectory) {
|
2020-07-26 21:16:06 +02:00
|
|
|
val result = recursiveRemoveDirectory(fullPath)
|
|
|
|
result?.let{ failedItem = it }
|
2020-07-17 16:35:39 +02:00
|
|
|
} else {
|
2020-08-01 16:43:48 +02:00
|
|
|
if (!gocryptfsVolume.removeFile(fullPath)) {
|
2020-07-26 21:16:06 +02:00
|
|
|
failedItem = fullPath
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-26 21:16:06 +02:00
|
|
|
if (failedItem != null) {
|
2020-07-27 16:20:52 +02:00
|
|
|
ColoredAlertDialogBuilder(this)
|
2020-07-17 16:35:39 +02:00
|
|
|
.setTitle(R.string.error)
|
2020-07-26 21:16:06 +02:00
|
|
|
.setMessage(getString(R.string.remove_failed, failedItem))
|
2020-07-17 16:35:39 +02:00
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2020-07-28 22:25:10 +02:00
|
|
|
unselectAll()
|
2020-07-26 21:16:06 +02:00
|
|
|
setCurrentPath(currentDirectoryPath) //refresh
|
2020-07-17 16:35:39 +02:00
|
|
|
}
|
|
|
|
}
|