Browse Source

Volume renaming

master
Hardcore Sushi 3 months ago
parent
commit
4a55d826d9
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
  1. 40
      app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt
  2. 48
      app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt
  3. 28
      app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt
  4. 9
      app/src/main/java/sushi/hardcore/droidfs/VolumeDatabase.kt
  5. 95
      app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt
  6. 27
      app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt
  7. 2
      app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt
  8. 32
      app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt
  9. 6
      app/src/main/res/menu/main_activity.xml
  10. 1
      app/src/main/res/values-pt-rBR/strings.xml
  11. 1
      app/src/main/res/values-ru/strings.xml
  12. 3
      app/src/main/res/values/strings.xml

40
app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt

@ -13,11 +13,9 @@ import android.util.Size
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.view.WindowManager
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import android.widget.EditText
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.Toast
@ -35,6 +33,7 @@ import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.video_recording.SeekableWriter
import sushi.hardcore.droidfs.video_recording.VideoCapture
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
@ -161,29 +160,16 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
}
}
binding.imageTimer.setOnClickListener {
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
dialogEditText.inputType = InputType.TYPE_CLASS_NUMBER
val dialog = CustomAlertDialogBuilder(this, themeValue)
.setView(dialogEditTextView)
.setTitle(getString(R.string.enter_timer_duration))
.setPositiveButton(R.string.ok) { _, _ ->
val enteredValue = dialogEditText.text.toString()
if (enteredValue.isEmpty()){
Toast.makeText(this, getString(R.string.timer_empty_error_msg), Toast.LENGTH_SHORT).show()
} else {
timerDuration = enteredValue.toInt()
}
with (EditTextDialog(this, R.string.enter_timer_duration) {
try {
timerDuration = it.toInt()
} catch (e: NumberFormatException) {
Toast.makeText(this, R.string.invalid_number, Toast.LENGTH_SHORT).show()
}
.setNegativeButton(R.string.cancel, null)
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
timerDuration = dialogEditText.text.toString().toInt()
dialog.dismiss()
true
}) {
binding.dialogEditText.inputType = InputType.TYPE_CLASS_NUMBER
show()
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
}
binding.imageFlash.setOnClickListener {
binding.imageFlash.setImageResource(if (isInVideoMode) {
@ -384,9 +370,11 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
runOnUiThread { binding.textTimer.text = i.toString() }
Thread.sleep(1000)
}
runOnUiThread {
action()
binding.textTimer.visibility = View.GONE
if (!isFinishing) {
runOnUiThread {
action()
binding.textTimer.visibility = View.GONE
}
}
isWaitingForTimer = false
}.start()

48
app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt

@ -30,6 +30,7 @@ import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
import sushi.hardcore.droidfs.file_operations.FileOperationService
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog
import java.io.File
import java.util.*
@ -78,7 +79,12 @@ class MainActivity : BaseActivity() {
startActivity(intent)
}
.setNegativeButton(R.string.ok, null)
.setOnDismissListener { sharedPrefs.edit().putBoolean("applicationFirstOpening", false).apply() }
.setOnDismissListener {
with (sharedPrefs.edit()) {
putBoolean("applicationFirstOpening", false)
apply()
}
}
.show()
}
pickMode = intent.action == "pick"
@ -263,6 +269,11 @@ class MainActivity : BaseActivity() {
}
true
}
R.id.rename -> {
val position = volumeAdapter.selectedItems.elementAt(0)
renameVolume(volumeAdapter.volumes[position], position)
true
}
R.id.settings -> {
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
@ -288,10 +299,10 @@ class MainActivity : BaseActivity() {
}
}
menu.findItem(R.id.forget_password).isVisible = showForgetPassword && !pickMode
menu.findItem(R.id.change_password).isVisible =
!pickMode && !dropMode &&
volumeAdapter.selectedItems.size == 1 &&
volumeAdapter.volumes[volumeAdapter.selectedItems.elementAt(0)].canWrite(filesDir.path)
val onlyOneAndWriteable = !pickMode && !dropMode &&
volumeAdapter.selectedItems.size == 1 &&
volumeAdapter.volumes[volumeAdapter.selectedItems.elementAt(0)].canWrite(filesDir.path)
menu.findItem(R.id.change_password).isVisible = onlyOneAndWriteable
with(menu.findItem(R.id.copy)) {
isVisible = !pickMode && !dropMode && volumeAdapter.selectedItems.size == 1
if (isVisible) {
@ -302,6 +313,7 @@ class MainActivity : BaseActivity() {
)
}
}
menu.findItem(R.id.rename).isVisible = onlyOneAndWriteable
supportActionBar?.setDisplayHomeAsUpEnabled(isSelecting || pickMode || dropMode)
return true
}
@ -358,6 +370,32 @@ class MainActivity : BaseActivity() {
}
}
private fun renameVolume(volume: Volume, position: Int) {
EditTextDialog(this, R.string.new_volume_name) { newName ->
val srcPath = File(volume.getFullPath(filesDir.path))
val dstPath = File(srcPath.parent, newName).canonicalFile
val newDBName: String
val success = if (volume.isHidden) {
if (newName.contains("/")) {
Toast.makeText(this, R.string.error_slash_in_name, Toast.LENGTH_SHORT).show()
renameVolume(volume, position)
return@EditTextDialog
}
newDBName = newName
srcPath.renameTo(dstPath)
} else {
newDBName = dstPath.path
DocumentFile.fromFile(srcPath).renameTo(newName)
}
if (success) {
volumeDatabase.renameVolume(volume.name, newDBName)
unselect(position)
} else {
Toast.makeText(this, R.string.volume_rename_failed, Toast.LENGTH_SHORT).show()
}
}.show()
}
@SuppressLint("NewApi") // fingerprintProtector is non-null only when SDK_INT >= 23
private fun openVolume(volume: Volume, position: Int) {
var askForPassword = true

28
app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt

@ -3,18 +3,17 @@ package sushi.hardcore.droidfs
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.text.InputType
import android.view.MenuItem
import android.view.inputmethod.EditorInfo
import android.widget.Toast
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import sushi.hardcore.droidfs.databinding.ActivitySettingsBinding
import sushi.hardcore.droidfs.databinding.DialogEditTextBinding
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.lang.NumberFormatException
import sushi.hardcore.droidfs.widgets.EditTextDialog
class SettingsActivity : BaseActivity() {
@ -71,24 +70,15 @@ class SettingsActivity : BaseActivity() {
}
private fun showMaxSizeDialog() {
val dialogBinding = DialogEditTextBinding.inflate(layoutInflater)
with (dialogBinding.dialogEditText) {
inputType = EditorInfo.TYPE_CLASS_NUMBER
hint = getString(R.string.size_hint)
}
val dialog = CustomAlertDialogBuilder(requireContext(), (requireActivity() as BaseActivity).themeValue)
.setTitle(R.string.thumbnail_max_size)
.setView(dialogBinding.root)
.setPositiveButton(R.string.ok) { _, _ ->
setThumbnailMaxSize(dialogBinding.dialogEditText.text.toString())
with (EditTextDialog((requireActivity() as BaseActivity), R.string.thumbnail_max_size) {
setThumbnailMaxSize(it)
}) {
with (binding.dialogEditText) {
inputType = InputType.TYPE_CLASS_NUMBER
hint = getString(R.string.size_hint)
}
.create()
dialogBinding.dialogEditText.setOnEditorActionListener { _, _, _ ->
dialog.dismiss()
setThumbnailMaxSize(dialogBinding.dialogEditText.text.toString())
true
show()
}
dialog.show()
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {

9
app/src/main/java/sushi/hardcore/droidfs/VolumeDatabase.kt

@ -94,6 +94,15 @@ class VolumeDatabase(context: Context): SQLiteOpenHelper(context,
), "$COLUMN_NAME=?", arrayOf(volume.name)) > 0
}
fun renameVolume(oldName: String, newName: String): Boolean {
return writableDatabase.update(TABLE_NAME,
ContentValues().apply {
put(COLUMN_NAME, newName)
},
"$COLUMN_NAME=?",arrayOf(oldName)
) > 0
}
fun removeVolume(volumeName: String): Boolean {
return writableDatabase.delete(TABLE_NAME, "$COLUMN_NAME=?", arrayOf(volumeName)) > 0
}

95
app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt

@ -10,8 +10,6 @@ import android.os.IBinder
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
@ -39,6 +37,7 @@ import sushi.hardcore.droidfs.file_operations.OperationFile
import sushi.hardcore.droidfs.file_viewers.*
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog
open class BaseExplorerActivity : BaseActivity() {
private lateinit var sortOrderEntries: Array<String>
@ -314,25 +313,9 @@ open class BaseExplorerActivity : BaseActivity() {
}
protected fun openDialogCreateFolder() {
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
val dialog = CustomAlertDialogBuilder(this, themeValue)
.setView(dialogEditTextView)
.setTitle(R.string.enter_folder_name)
.setPositiveButton(R.string.ok) { _, _ ->
val folderName = dialogEditText.text.toString()
createFolder(folderName)
}
.setNegativeButton(R.string.cancel, null)
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
val folderName = dialogEditText.text.toString()
dialog.dismiss()
createFolder(folderName)
true
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
EditTextDialog(this, R.string.enter_folder_name) {
createFolder(it)
}.show()
}
protected fun checkPathOverwrite(items: ArrayList<OperationFile>, dstDirectoryPath: String, callback: (ArrayList<OperationFile>?) -> Unit) {
@ -363,36 +346,26 @@ open class BaseExplorerActivity : BaseActivity() {
checkPathOverwrite(items, dstDirectoryPath, callback)
}
.setNegativeButton(R.string.no) { _, _ ->
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
dialogEditText.setText(items[i].explorerElement.name)
dialogEditText.selectAll()
val dialog = CustomAlertDialogBuilder(this, themeValue)
.setView(dialogEditTextView)
.setTitle(R.string.enter_new_name)
.setPositiveButton(R.string.ok) { _, _ ->
items[i].dstPath = PathUtils.pathJoin(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, items[i].explorerElement.parentPath), dialogEditText.text.toString())
if (items[i].explorerElement.isDirectory){
for (j in 0 until items.size){
if (PathUtils.isChildOf(items[j].explorerElement.fullPath, items[i].explorerElement.fullPath)){
items[j].dstPath = PathUtils.pathJoin(items[i].dstPath!!, PathUtils.getRelativePath(items[i].explorerElement.fullPath, items[j].explorerElement.fullPath))
}
}
with(EditTextDialog(this, R.string.enter_new_name) {
items[i].dstPath = PathUtils.pathJoin(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, items[i].explorerElement.parentPath), it)
if (items[i].explorerElement.isDirectory){
for (j in 0 until items.size){
if (PathUtils.isChildOf(items[j].explorerElement.fullPath, items[i].explorerElement.fullPath)){
items[j].dstPath = PathUtils.pathJoin(items[i].dstPath!!, PathUtils.getRelativePath(items[i].explorerElement.fullPath, items[j].explorerElement.fullPath))
}
checkPathOverwrite(items, dstDirectoryPath, callback)
}
.setOnCancelListener{
callback(null)
}
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
dialog.dismiss()
items[i].dstPath = PathUtils.pathJoin(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, items[i].explorerElement.parentPath), dialogEditText.text.toString())
}
checkPathOverwrite(items, dstDirectoryPath, callback)
true
}) {
with (binding.dialogEditText) {
setText(items[i].explorerElement.name)
selectAll()
}
setOnCancelListener{
callback(null)
}
show()
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
}
.setOnCancelListener{
callback(null)
@ -521,28 +494,16 @@ open class BaseExplorerActivity : BaseActivity() {
true
}
R.id.rename -> {
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val oldName = explorerElements[explorerAdapter.selectedItems[0]].name
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
dialogEditText.setText(oldName)
dialogEditText.selectAll()
val dialog = CustomAlertDialogBuilder(this, themeValue)
.setView(dialogEditTextView)
.setTitle(R.string.rename_title)
.setPositiveButton(R.string.ok) { _, _ ->
val newName = dialogEditText.text.toString()
rename(oldName, newName)
}
.setNegativeButton(R.string.cancel, null)
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
val newName = dialogEditText.text.toString()
dialog.dismiss()
rename(oldName, newName)
true
with(EditTextDialog(this, R.string.rename_title) {
rename(oldName, it)
}) {
with(binding.dialogEditText) {
setText(oldName)
selectAll()
}
show()
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
true
}
R.id.open_as -> {

27
app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt

@ -5,8 +5,6 @@ import android.content.Intent
import android.net.Uri
import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager
import android.widget.EditText
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.documentfile.provider.DocumentFile
@ -20,6 +18,7 @@ import sushi.hardcore.droidfs.databinding.ActivityExplorerBinding
import sushi.hardcore.droidfs.file_operations.OperationFile
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog
import java.io.File
class ExplorerActivity : BaseExplorerActivity() {
@ -192,25 +191,9 @@ class ExplorerActivity : BaseExplorerActivity() {
pickImportDirectory.launch(null)
}
"createFile" -> {
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
val dialog = CustomAlertDialogBuilder(this, themeValue)
.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()
EditTextDialog(this, R.string.enter_file_name) {
createNewFile(it)
}.show()
}
"createFolder" -> {
openDialogCreateFolder()
@ -343,6 +326,7 @@ class ExplorerActivity : BaseExplorerActivity() {
}
}
cancelItemAction()
invalidateOptionsMenu()
}
} else if (currentItemAction == ItemsActions.MOVE){
mapFileForMove(itemsToProcess, itemsToProcess[0].explorerElement.parentPath)
@ -364,6 +348,7 @@ class ExplorerActivity : BaseExplorerActivity() {
}
}
cancelItemAction()
invalidateOptionsMenu()
}
}
true

2
app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt

@ -8,7 +8,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import sushi.hardcore.droidfs.R
class CustomAlertDialogBuilder(context: Context, theme: String) : AlertDialog.Builder(
open class CustomAlertDialogBuilder(context: Context, theme: String) : AlertDialog.Builder(
context, when (theme) {
"black_green" -> R.style.BlackGreenDialog
"dark_red" -> R.style.DarkRedDialog

32
app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt

@ -0,0 +1,32 @@
package sushi.hardcore.droidfs.widgets
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import sushi.hardcore.droidfs.BaseActivity
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.databinding.DialogEditTextBinding
class EditTextDialog(
activity: BaseActivity,
private val titleId: Int,
private val callback: (String) -> Unit,
): CustomAlertDialogBuilder(activity, activity.themeValue) {
val binding = DialogEditTextBinding.inflate(activity.layoutInflater)
override fun create(): AlertDialog {
setTitle(titleId)
setView(binding.root)
setPositiveButton(R.string.ok) { _, _ ->
callback(binding.dialogEditText.text.toString())
}
setNegativeButton(R.string.cancel, null)
val dialog = super.create()
binding.dialogEditText.setOnEditorActionListener { _, _, _ ->
dialog.dismiss()
callback(binding.dialogEditText.text.toString())
true
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
return dialog
}
}

6
app/src/main/res/menu/main_activity.xml

@ -39,4 +39,10 @@
app:showAsAction="never"
android:visible="false"/>
<item
android:id="@+id/rename"
app:showAsAction="never"
android:visible="false"
android:title="@string/rename"/>
</menu>

1
app/src/main/res/values-pt-rBR/strings.xml

@ -127,7 +127,6 @@
<string name="move_failed">Transferência do arquivo %s falhou.</string>
<string name="move_success">Transferência bem sucedida!</string>
<string name="enter_timer_duration">Definir a duração do tempo (em s)</string>
<string name="timer_empty_error_msg">Por favor, digite um valor numérico</string>
<string name="path_error">Falha ao carregar a localização selecionada.</string>
<string name="create_cant_write_error_msg">DroidFS não pode salvar neste local. Por favor, tente algum outro.</string>
<string name="sdcard_error_header">DroidFS só pode escrever em memórias SD removíveis sob:</string>

1
app/src/main/res/values-ru/strings.xml

@ -122,7 +122,6 @@
<string name="move_failed">Ошибка при перемещении %s.</string>
<string name="move_success">Перемещение выполнено!</string>
<string name="enter_timer_duration">Введите время таймера (в сек.)</string>
<string name="timer_empty_error_msg">Введите числовое значение.</string>
<string name="path_error">Невозможно получить выбранный путь.</string>
<string name="create_cant_write_error_msg">DroidFS не имеет доступа на запись по этому пути. Попробуйте найти другое место.</string>
<string name="add_cant_write_warning">DroidFS не имеет доступа на запись по этому пути. Добавление тома с доступом только для чтения.</string>

3
app/src/main/res/values/strings.xml

@ -127,7 +127,6 @@
<string name="move_failed">Move of %s failed.</string>
<string name="move_success">Move successful !</string>
<string name="enter_timer_duration">Enter the timer duration (in s)</string>
<string name="timer_empty_error_msg">Please enter a numeric value</string>
<string name="path_error">Failed to retrieve the selected path.</string>
<string name="create_cant_write_error_msg">DroidFS doesn\'t have write access to this path. Please try another location.</string>
<string name="add_cant_write_warning">DroidFS doesn\'t have write access to this path. Adding volume with read-only access.</string>
@ -232,4 +231,6 @@
<string name="thumbnail_max_size_summary">Maximum file size for which to load a thumbnail. Current value: %s</string>
<string name="size_hint">Size (in KB)</string>
<string name="invalid_number">Invalid number</string>
<string name="new_volume_name">New volume name:</string>
<string name="volume_rename_failed">Failed to rename volume</string>
</resources>

Loading…
Cancel
Save