2020-07-17 16:35:39 +02:00
|
|
|
package sushi.hardcore.droidfs.explorers
|
|
|
|
|
|
|
|
import android.content.Intent
|
|
|
|
import android.content.SharedPreferences
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.view.Menu
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.View
|
|
|
|
import android.view.WindowManager
|
|
|
|
import android.widget.AdapterView.OnItemClickListener
|
|
|
|
import android.widget.AdapterView.OnItemLongClickListener
|
|
|
|
import android.widget.EditText
|
|
|
|
import android.widget.ListView
|
|
|
|
import android.widget.Toast
|
|
|
|
import com.github.clans.fab.FloatingActionMenu
|
|
|
|
import kotlinx.android.synthetic.main.activity_explorer_ro.*
|
|
|
|
import kotlinx.android.synthetic.main.explorer_info_bar.*
|
|
|
|
import kotlinx.android.synthetic.main.toolbar.*
|
|
|
|
import sushi.hardcore.droidfs.ColoredActivity
|
|
|
|
import sushi.hardcore.droidfs.ConstValues
|
|
|
|
import sushi.hardcore.droidfs.ConstValues.Companion.isAudio
|
|
|
|
import sushi.hardcore.droidfs.ConstValues.Companion.isImage
|
|
|
|
import sushi.hardcore.droidfs.ConstValues.Companion.isText
|
|
|
|
import sushi.hardcore.droidfs.ConstValues.Companion.isVideo
|
|
|
|
import sushi.hardcore.droidfs.R
|
|
|
|
import sushi.hardcore.droidfs.adapters.OpenAsDialogAdapter
|
|
|
|
import sushi.hardcore.droidfs.adapters.ExplorerElementAdapter
|
|
|
|
import sushi.hardcore.droidfs.file_viewers.AudioPlayer
|
|
|
|
import sushi.hardcore.droidfs.file_viewers.ImageViewer
|
|
|
|
import sushi.hardcore.droidfs.file_viewers.TextEditor
|
|
|
|
import sushi.hardcore.droidfs.file_viewers.VideoPlayer
|
|
|
|
import sushi.hardcore.droidfs.provider.TemporaryFileProvider
|
|
|
|
import sushi.hardcore.droidfs.util.ExternalProvider
|
|
|
|
import sushi.hardcore.droidfs.util.FilesUtils
|
|
|
|
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
|
|
|
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
|
|
|
|
import java.util.*
|
|
|
|
|
|
|
|
open class ExplorerActivityRO : ColoredActivity() {
|
|
|
|
private lateinit var shared_prefs_editor: SharedPreferences.Editor
|
|
|
|
private lateinit var sort_modes_entries: Array<String>
|
|
|
|
private lateinit var sort_modes_values: Array<String>
|
|
|
|
private var current_sort_mode_index = 0
|
|
|
|
protected lateinit var gocryptfsVolume: GocryptfsVolume
|
|
|
|
private lateinit var volume_name: String
|
|
|
|
protected var current_path = ""
|
|
|
|
protected lateinit var explorer_elements: MutableList<ExplorerElement>
|
|
|
|
protected lateinit var explorer_adapter: ExplorerElementAdapter
|
|
|
|
private var usf_open = false
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
if (!sharedPrefs.getBoolean("usf_screenshot", false)){
|
|
|
|
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
|
|
|
|
}
|
|
|
|
usf_open = sharedPrefs.getBoolean("usf_open", false)
|
|
|
|
val intent = intent
|
2020-07-18 18:44:53 +02:00
|
|
|
volume_name = intent.getStringExtra("volume_name") ?: ""
|
2020-07-17 16:35:39 +02:00
|
|
|
val sessionID = intent.getIntExtra("sessionID", -1)
|
|
|
|
gocryptfsVolume = GocryptfsVolume(sessionID)
|
|
|
|
sort_modes_entries = resources.getStringArray(R.array.sort_orders_entries)
|
|
|
|
sort_modes_values = resources.getStringArray(R.array.sort_orders_values)
|
|
|
|
current_sort_mode_index = resources.getStringArray(R.array.sort_orders_values).indexOf(sharedPrefs.getString(ConstValues.sort_order_key, "name"))
|
|
|
|
shared_prefs_editor = sharedPrefs.edit()
|
|
|
|
init()
|
|
|
|
setSupportActionBar(toolbar)
|
|
|
|
title = ""
|
|
|
|
title_text.text = getString(R.string.volume, volume_name)
|
|
|
|
explorer_adapter = ExplorerElementAdapter(this)
|
|
|
|
setCurrentPath(current_path)
|
|
|
|
list_explorer.adapter = explorer_adapter
|
|
|
|
list_explorer.onItemClickListener = OnItemClickListener { _, _, position, _ -> onExplorerItemClick(position) }
|
|
|
|
list_explorer.onItemLongClickListener = OnItemLongClickListener { _, _, position, _ ->
|
|
|
|
explorer_adapter.onItemLongClick(position)
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
true
|
|
|
|
}
|
|
|
|
refresher.setOnRefreshListener {
|
|
|
|
setCurrentPath(current_path)
|
|
|
|
refresher.isRefreshing = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected open fun init() {
|
|
|
|
setContentView(R.layout.activity_explorer_ro)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun startFileViewer(cls: Class<*>, filePath: String){
|
|
|
|
val intent = Intent(this, cls)
|
|
|
|
intent.putExtra("path", filePath)
|
|
|
|
intent.putExtra("sessionID", gocryptfsVolume.sessionID)
|
|
|
|
startActivity(intent)
|
|
|
|
}
|
|
|
|
|
|
|
|
protected open fun onExplorerItemClick(position: Int) {
|
|
|
|
val wasSelecting = explorer_adapter.selectedItems.isNotEmpty()
|
|
|
|
explorer_adapter.onItemClick(position)
|
|
|
|
if (explorer_adapter.selectedItems.isEmpty()) {
|
|
|
|
if (!wasSelecting) {
|
|
|
|
val full_path = FilesUtils.path_join(current_path, explorer_elements[position].name)
|
|
|
|
when {
|
|
|
|
explorer_elements[position].isDirectory -> {
|
|
|
|
setCurrentPath(full_path)
|
|
|
|
}
|
|
|
|
explorer_elements[position].isParentFolder -> {
|
|
|
|
setCurrentPath(FilesUtils.get_parent_path(current_path))
|
|
|
|
}
|
|
|
|
isImage(full_path) -> {
|
|
|
|
startFileViewer(ImageViewer::class.java, full_path)
|
|
|
|
}
|
|
|
|
isVideo(full_path) -> {
|
|
|
|
startFileViewer(VideoPlayer::class.java, full_path)
|
|
|
|
}
|
|
|
|
isText(full_path) -> {
|
|
|
|
startFileViewer(TextEditor::class.java, full_path)
|
|
|
|
}
|
|
|
|
isAudio(full_path) -> {
|
|
|
|
startFileViewer(AudioPlayer::class.java, full_path)
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
val dialogListView = layoutInflater.inflate(R.layout.dialog_listview, null)
|
|
|
|
val listView = dialogListView.findViewById<ListView>(R.id.listview)
|
|
|
|
val adapter = OpenAsDialogAdapter(this)
|
|
|
|
listView.adapter = adapter
|
|
|
|
val dialog = ColoredAlertDialog(this)
|
|
|
|
.setView(dialogListView)
|
|
|
|
.setTitle(getString(R.string.open_as))
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.create()
|
|
|
|
listView.setOnItemClickListener{_, _, fileTypePosition, _ ->
|
|
|
|
when (adapter.getItem(fileTypePosition)){
|
|
|
|
"image" -> startFileViewer(ImageViewer::class.java, full_path)
|
|
|
|
"video" -> startFileViewer(VideoPlayer::class.java, full_path)
|
|
|
|
"audio" -> startFileViewer(AudioPlayer::class.java, full_path)
|
|
|
|
"text" -> startFileViewer(TextEditor::class.java, full_path)
|
|
|
|
}
|
|
|
|
dialog.dismiss()
|
|
|
|
}
|
|
|
|
dialog.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
|
2020-07-18 18:44:53 +02:00
|
|
|
private fun sortExplorerElements() {
|
2020-07-17 16:35:39 +02:00
|
|
|
when (sort_modes_values[current_sort_mode_index]) {
|
|
|
|
"name" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> o1.name.compareTo(o2.name) })
|
|
|
|
}
|
|
|
|
"size" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> (o1.size - o2.size).toInt() })
|
|
|
|
}
|
|
|
|
"date" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> o1.mTime.compareTo(o2.mTime) })
|
|
|
|
}
|
|
|
|
"name_desc" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> o2.name.compareTo(o1.name) })
|
|
|
|
}
|
|
|
|
"size_desc" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> (o2.size - o1.size).toInt() })
|
|
|
|
}
|
|
|
|
"date_desc" -> {
|
|
|
|
explorer_elements.sortWith(Comparator { o1, o2 -> o2.mTime.compareTo(o1.mTime) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
shared_prefs_editor.putString(ConstValues.sort_order_key, sort_modes_values[current_sort_mode_index])
|
|
|
|
shared_prefs_editor.apply()
|
|
|
|
}
|
|
|
|
|
|
|
|
protected fun setCurrentPath(path: String) {
|
|
|
|
explorer_elements = gocryptfsVolume.list_dir(path)
|
|
|
|
text_dir_empty.visibility = if (explorer_elements.size == 0) View.VISIBLE else View.INVISIBLE
|
2020-07-18 18:44:53 +02:00
|
|
|
sortExplorerElements()
|
2020-07-17 16:35:39 +02:00
|
|
|
if (path.isNotEmpty()) { //not root
|
|
|
|
explorer_elements.add(0, ExplorerElement("..", (-1).toShort(), -1, -1))
|
|
|
|
}
|
|
|
|
explorer_adapter.setExplorerElements(explorer_elements)
|
|
|
|
current_path = path
|
|
|
|
current_path_text.text = getString(R.string.location, current_path)
|
|
|
|
total_size_text.text = getString(R.string.total_size, FilesUtils.formatSize(explorer_adapter.currentDirectoryTotalSize))
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun askCloseVolume() {
|
|
|
|
ColoredAlertDialog(this)
|
|
|
|
.setTitle(R.string.warning)
|
|
|
|
.setMessage(R.string.ask_close_volume)
|
|
|
|
.setPositiveButton(R.string.ok) { _, _ -> closeVolumeOnUserExit() }
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
protected open fun closeVolumeOnUserExit() {
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
protected open fun closeVolumeOnDestroy() {
|
|
|
|
gocryptfsVolume.close()
|
|
|
|
TemporaryFileProvider.wipeAll() //additional security
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onBackPressed() {
|
|
|
|
if (explorer_adapter.selectedItems.isEmpty()) {
|
|
|
|
val parent_path = FilesUtils.get_parent_path(current_path)
|
|
|
|
if (parent_path == current_path) {
|
|
|
|
askCloseVolume()
|
|
|
|
} else {
|
|
|
|
setCurrentPath(FilesUtils.get_parent_path(current_path))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
explorer_adapter.unSelectAll()
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-18 18:44:53 +02:00
|
|
|
private fun createFolder(folder_name: String){
|
2020-07-17 16:35:39 +02:00
|
|
|
if (folder_name.isEmpty()) {
|
|
|
|
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
|
|
|
|
} else {
|
|
|
|
if (!gocryptfsVolume.mkdir(FilesUtils.path_join(current_path, folder_name))) {
|
|
|
|
ColoredAlertDialog(this)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(R.string.error_mkdir)
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
} else {
|
|
|
|
setCurrentPath(current_path)
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun onClickAddFolder(view: View?) {
|
|
|
|
findViewById<FloatingActionMenu>(R.id.fam_explorer).close(true)
|
|
|
|
val dialog_edit_text_view = layoutInflater.inflate(R.layout.dialog_edit_text, null)
|
|
|
|
val dialog_edit_text = dialog_edit_text_view.findViewById<EditText>(R.id.dialog_edit_text)
|
|
|
|
val dialog = ColoredAlertDialog(this)
|
|
|
|
.setView(dialog_edit_text_view)
|
|
|
|
.setTitle(R.string.enter_folder_name)
|
|
|
|
.setPositiveButton(R.string.ok) { _, _ ->
|
|
|
|
val folder_name = dialog_edit_text.text.toString()
|
|
|
|
createFolder(folder_name)
|
|
|
|
}
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.create()
|
|
|
|
dialog_edit_text.setOnEditorActionListener { _, _, _ ->
|
|
|
|
val folder_name = dialog_edit_text.text.toString()
|
|
|
|
dialog.dismiss()
|
|
|
|
createFolder(folder_name)
|
|
|
|
true
|
|
|
|
}
|
|
|
|
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
|
|
|
dialog.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun rename(old_name: String, new_name: String){
|
|
|
|
if (new_name.isEmpty()) {
|
|
|
|
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
|
|
|
|
} else {
|
|
|
|
if (!gocryptfsVolume.rename(FilesUtils.path_join(current_path, old_name), FilesUtils.path_join(current_path, new_name))) {
|
|
|
|
ColoredAlertDialog(this)
|
|
|
|
.setTitle(R.string.error)
|
|
|
|
.setMessage(getString(R.string.rename_failed, old_name))
|
|
|
|
.setPositiveButton(R.string.ok, null)
|
|
|
|
.show()
|
|
|
|
} else {
|
|
|
|
setCurrentPath(current_path)
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-18 18:44:53 +02:00
|
|
|
fun handleMenuItems(menu: Menu){
|
2020-07-17 16:35:39 +02:00
|
|
|
menu.findItem(R.id.explorer_menu_rename).isVisible = false
|
|
|
|
if (usf_open){
|
|
|
|
menu.findItem(R.id.explorer_menu_external_open)?.isVisible = false
|
|
|
|
}
|
|
|
|
val selectedItems = explorer_adapter.selectedItems
|
|
|
|
if (selectedItems.isEmpty()){
|
|
|
|
toolbar.navigationIcon = null
|
|
|
|
menu.findItem(R.id.explorer_menu_close).isVisible = true
|
|
|
|
menu.findItem(R.id.explorer_menu_sort).isVisible = true
|
|
|
|
} else {
|
|
|
|
toolbar.setNavigationIcon(R.drawable.icon_arrow_back)
|
|
|
|
menu.findItem(R.id.explorer_menu_close).isVisible = false
|
|
|
|
menu.findItem(R.id.explorer_menu_sort).isVisible = false
|
|
|
|
if (selectedItems.size == 1) {
|
|
|
|
menu.findItem(R.id.explorer_menu_rename).isVisible = true
|
|
|
|
if (usf_open && explorer_elements[selectedItems[0]].isRegularFile) {
|
|
|
|
menu.findItem(R.id.explorer_menu_external_open)?.isVisible = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
return when (item.itemId) {
|
|
|
|
android.R.id.home -> {
|
|
|
|
explorer_adapter.unSelectAll()
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.explorer_menu_sort -> {
|
|
|
|
ColoredAlertDialog(this)
|
|
|
|
.setTitle(R.string.sort_order)
|
|
|
|
.setSingleChoiceItems(sort_modes_entries, current_sort_mode_index) { dialog, which ->
|
|
|
|
current_sort_mode_index = which
|
|
|
|
setCurrentPath(current_path)
|
|
|
|
dialog.dismiss()
|
|
|
|
}.show()
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.explorer_menu_rename -> {
|
|
|
|
val dialog_edit_text_view = layoutInflater.inflate(R.layout.dialog_edit_text, null)
|
|
|
|
val old_name = explorer_elements[explorer_adapter.selectedItems[0]].name
|
|
|
|
val dialog_edit_text = dialog_edit_text_view.findViewById<EditText>(R.id.dialog_edit_text)
|
|
|
|
dialog_edit_text.setText(old_name)
|
|
|
|
dialog_edit_text.selectAll()
|
|
|
|
val dialog = ColoredAlertDialog(this)
|
|
|
|
.setView(dialog_edit_text_view)
|
|
|
|
.setTitle(R.string.rename_title)
|
|
|
|
.setPositiveButton(R.string.ok) { _, _ ->
|
|
|
|
val new_name = dialog_edit_text.text.toString()
|
|
|
|
rename(old_name, new_name)
|
|
|
|
}
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
.create()
|
|
|
|
dialog_edit_text.setOnEditorActionListener { _, _, _ ->
|
|
|
|
val new_name = dialog_edit_text.text.toString()
|
|
|
|
dialog.dismiss()
|
|
|
|
rename(old_name, new_name)
|
|
|
|
true
|
|
|
|
}
|
|
|
|
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
|
|
|
dialog.show()
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.explorer_menu_external_open -> {
|
|
|
|
if (usf_open){
|
|
|
|
ExternalProvider.open(this, gocryptfsVolume, FilesUtils.path_join(current_path, explorer_elements[explorer_adapter.selectedItems[0]].name))
|
|
|
|
explorer_adapter.unSelectAll()
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
R.id.explorer_menu_close -> {
|
|
|
|
askCloseVolume()
|
|
|
|
true
|
|
|
|
}
|
|
|
|
else -> super.onOptionsItemSelected(item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onDestroy() {
|
|
|
|
super.onDestroy()
|
|
|
|
if (!isChangingConfigurations) { //activity won't be recreated
|
|
|
|
closeVolumeOnDestroy()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
super.onResume()
|
|
|
|
ExternalProvider.clear_cache(this)
|
|
|
|
}
|
|
|
|
}
|