Improve volume adding UI
This commit is contained in:
parent
85e24921fa
commit
c0dcaed8d2
@ -79,10 +79,12 @@ class VolumeData(
|
|||||||
if (other !is VolumeData) {
|
if (other !is VolumeData) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return other.uuid == uuid
|
return other.uuid == uuid || (other.name == name && other.isHidden == isHidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode() = uuid.hashCode()
|
override fun hashCode(): Int {
|
||||||
|
return name.hashCode()+isHidden.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VOLUMES_DIRECTORY = "volumes"
|
const val VOLUMES_DIRECTORY = "volumes"
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
package sushi.hardcore.droidfs.add_volume
|
package sushi.hardcore.droidfs.add_volume
|
||||||
|
|
||||||
|
import sushi.hardcore.droidfs.R
|
||||||
|
|
||||||
enum class Action {
|
enum class Action {
|
||||||
|
OPEN,
|
||||||
ADD,
|
ADD,
|
||||||
CREATE,
|
CREATE,
|
||||||
|
;
|
||||||
|
|
||||||
|
fun getStringResId() = when (this) {
|
||||||
|
OPEN -> R.string.open
|
||||||
|
ADD -> R.string.add_volume
|
||||||
|
CREATE -> R.string.create_volume
|
||||||
|
}
|
||||||
}
|
}
|
@ -67,18 +67,18 @@ class AddVolumeActivity: BaseActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onVolumeSelected(volume: VolumeData, rememberVolume: Boolean) {
|
fun onVolumeAdded() {
|
||||||
if (rememberVolume) {
|
|
||||||
setResult(RESULT_USER_BACK)
|
setResult(RESULT_USER_BACK)
|
||||||
finish()
|
finish()
|
||||||
} else {
|
}
|
||||||
volumeOpener.openVolume(volume, false, object : VolumeOpener.VolumeOpenerCallbacks {
|
|
||||||
|
fun openVolume(volume: VolumeData, isVolumeKnown: Boolean) {
|
||||||
|
volumeOpener.openVolume(volume, isVolumeKnown, object : VolumeOpener.VolumeOpenerCallbacks {
|
||||||
override fun onVolumeOpened(id: Int) {
|
override fun onVolumeOpened(id: Int) {
|
||||||
startExplorer(id, volume.shortName)
|
startExplorer(id, volume.shortName)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun createVolume(volumePath: String, isHidden: Boolean, rememberVolume: Boolean) {
|
fun createVolume(volumePath: String, isHidden: Boolean, rememberVolume: Boolean) {
|
||||||
supportFragmentManager
|
supportFragmentManager
|
||||||
|
@ -2,6 +2,7 @@ package sushi.hardcore.droidfs.add_volume
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@ -15,10 +16,14 @@ import android.text.TextWatcher
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import sushi.hardcore.droidfs.Constants
|
import sushi.hardcore.droidfs.Constants
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
@ -35,6 +40,10 @@ import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class SelectPathFragment: Fragment() {
|
class SelectPathFragment: Fragment() {
|
||||||
|
internal class InputViewModel: ViewModel() {
|
||||||
|
var showEditText = false
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val KEY_THEME_VALUE = "theme"
|
private const val KEY_THEME_VALUE = "theme"
|
||||||
private const val KEY_PICK_MODE = "pick"
|
private const val KEY_PICK_MODE = "pick"
|
||||||
@ -74,6 +83,7 @@ class SelectPathFragment: Fragment() {
|
|||||||
private var originalRememberVolume = true
|
private var originalRememberVolume = true
|
||||||
private var currentVolumeData: VolumeData? = null
|
private var currentVolumeData: VolumeData? = null
|
||||||
private var volumeAction: Action? = null
|
private var volumeAction: Action? = null
|
||||||
|
private val inputViewModel: InputViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
@ -93,17 +103,13 @@ class SelectPathFragment: Fragment() {
|
|||||||
theme = Compat.getParcelable(arguments, KEY_THEME_VALUE)!!
|
theme = Compat.getParcelable(arguments, KEY_THEME_VALUE)!!
|
||||||
pickMode = arguments.getBoolean(KEY_PICK_MODE)
|
pickMode = arguments.getBoolean(KEY_PICK_MODE)
|
||||||
}
|
}
|
||||||
if (pickMode) {
|
|
||||||
binding.buttonAction.text = getString(R.string.add_volume)
|
|
||||||
}
|
|
||||||
volumeDatabase = VolumeDatabase(requireContext())
|
volumeDatabase = VolumeDatabase(requireContext())
|
||||||
filesDir = requireContext().filesDir.path
|
filesDir = requireContext().filesDir.path
|
||||||
binding.containerHiddenVolume.setOnClickListener {
|
binding.containerHiddenVolume.setOnClickListener {
|
||||||
binding.switchHiddenVolume.performClick()
|
binding.switchHiddenVolume.performClick()
|
||||||
}
|
}
|
||||||
binding.switchHiddenVolume.setOnClickListener {
|
binding.switchHiddenVolume.setOnClickListener {
|
||||||
showRightSection()
|
updateUi()
|
||||||
refreshStatus(binding.editVolumeName.text)
|
|
||||||
}
|
}
|
||||||
binding.buttonPickDirectory.setOnClickListener {
|
binding.buttonPickDirectory.setOnClickListener {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
@ -137,22 +143,41 @@ class SelectPathFragment: Fragment() {
|
|||||||
launchPickDirectory()
|
launchPickDirectory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.buttonEnterPath.setOnClickListener {
|
||||||
|
inputViewModel.showEditText = true
|
||||||
|
updateUi()
|
||||||
|
binding.editVolumeName.requestFocus()
|
||||||
|
(app.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(
|
||||||
|
binding.editVolumeName,
|
||||||
|
InputMethodManager.SHOW_IMPLICIT
|
||||||
|
)
|
||||||
|
}
|
||||||
binding.editVolumeName.addTextChangedListener(object: TextWatcher {
|
binding.editVolumeName.addTextChangedListener(object: TextWatcher {
|
||||||
override fun afterTextChanged(s: Editable?) {}
|
override fun afterTextChanged(s: Editable?) {}
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
refreshStatus(s)
|
updateUi(s)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
binding.switchRemember.setOnCheckedChangeListener { _, _ -> refreshButtonText() }
|
binding.switchRemember.setOnCheckedChangeListener { _, _ -> updateUi() }
|
||||||
binding.editVolumeName.setOnEditorActionListener { _, _, _ -> onPathSelected(); true }
|
binding.editVolumeName.setOnEditorActionListener { _, _, _ ->
|
||||||
|
if (binding.editVolumeName.text.isEmpty()) {
|
||||||
|
Toast.makeText(
|
||||||
|
requireContext(),
|
||||||
|
if (binding.switchHiddenVolume.isChecked) R.string.empty_volume_name else R.string.empty_volume_path,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
onPathSelected()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
binding.buttonAction.setOnClickListener { onPathSelected() }
|
binding.buttonAction.setOnClickListener { onPathSelected() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||||
super.onViewStateRestored(savedInstanceState)
|
super.onViewStateRestored(savedInstanceState)
|
||||||
(activity as AddVolumeActivity).onFragmentLoaded(true)
|
(activity as AddVolumeActivity).onFragmentLoaded(true)
|
||||||
showRightSection()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchPickDirectory() {
|
private fun launchPickDirectory() {
|
||||||
@ -160,70 +185,83 @@ class SelectPathFragment: Fragment() {
|
|||||||
PathUtils.safePickDirectory(pickDirectory, requireContext(), theme)
|
PathUtils.safePickDirectory(pickDirectory, requireContext(), theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showRightSection() {
|
private fun updateUi(volumeName: CharSequence = binding.editVolumeName.text) {
|
||||||
if (binding.switchHiddenVolume.isChecked) {
|
var warning = -1
|
||||||
binding.textLabel.text = requireContext().getString(R.string.volume_name_label)
|
fun updateWarning() {
|
||||||
binding.editVolumeName.hint = requireContext().getString(R.string.volume_name_hint)
|
if (warning == -1) {
|
||||||
binding.buttonPickDirectory.visibility = View.GONE
|
binding.textWarning.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
binding.textLabel.text = requireContext().getString(R.string.volume_path_label)
|
binding.textWarning.isVisible = true
|
||||||
binding.editVolumeName.hint = requireContext().getString(R.string.volume_path_hint)
|
binding.textWarning.text = getString(warning)
|
||||||
binding.buttonPickDirectory.visibility = View.VISIBLE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshButtonText() {
|
val hidden = binding.switchHiddenVolume.isChecked
|
||||||
binding.buttonAction.text = getString(
|
binding.editVolumeName.isVisible = hidden || inputViewModel.showEditText
|
||||||
if (pickMode || volumeAction == Action.ADD) {
|
binding.buttonPickDirectory.isVisible = !hidden
|
||||||
if (binding.switchRemember.isChecked || currentVolumeData != null) {
|
binding.textOr.isVisible = !hidden && !inputViewModel.showEditText
|
||||||
R.string.add_volume
|
binding.buttonEnterPath.isVisible = !hidden && !inputViewModel.showEditText
|
||||||
|
if (hidden) {
|
||||||
|
binding.textLabel.text = getString(R.string.volume_name_label)
|
||||||
|
binding.editVolumeName.hint = getString(R.string.volume_name_hint)
|
||||||
} else {
|
} else {
|
||||||
R.string.open_volume
|
binding.textLabel.text = getString(R.string.volume_path_label)
|
||||||
|
binding.editVolumeName.hint = getString(R.string.volume_path_hint)
|
||||||
}
|
}
|
||||||
} else {
|
if (hidden && volumeName.contains(PathUtils.SEPARATOR)) {
|
||||||
R.string.create_volume
|
warning = R.string.error_slash_in_name
|
||||||
}
|
}
|
||||||
)
|
// exit early if possible to avoid filesystem queries
|
||||||
|
if (volumeName.isEmpty() || warning != -1 || (!hidden && !inputViewModel.showEditText)) {
|
||||||
|
binding.buttonAction.isVisible = false
|
||||||
|
binding.switchRemember.isVisible = false
|
||||||
|
updateWarning()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshStatus(content: CharSequence) {
|
|
||||||
val path = File(getCurrentVolumePath())
|
val path = File(getCurrentVolumePath())
|
||||||
volumeAction = if (path.isDirectory) {
|
volumeAction = if (path.isDirectory) {
|
||||||
if (path.list()?.isEmpty() == true || content.isEmpty()) Action.CREATE else Action.ADD
|
if (path.list()?.isEmpty() == true) {
|
||||||
|
Action.CREATE
|
||||||
|
} else if (pickMode || !binding.switchRemember.isChecked) {
|
||||||
|
Action.OPEN
|
||||||
|
} else {
|
||||||
|
Action.ADD
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Action.CREATE
|
Action.CREATE
|
||||||
}
|
}
|
||||||
|
val valid = !(volumeAction == Action.CREATE && pickMode)
|
||||||
|
binding.switchRemember.isVisible = valid
|
||||||
|
binding.buttonAction.isVisible = valid
|
||||||
|
if (valid) {
|
||||||
|
binding.buttonAction.text = getString(volumeAction!!.getStringResId())
|
||||||
currentVolumeData = if (volumeAction == Action.CREATE) {
|
currentVolumeData = if (volumeAction == Action.CREATE) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
volumeDatabase.getVolume(content.toString(), binding.switchHiddenVolume.isChecked)
|
volumeDatabase.getVolume(volumeName.toString(), hidden)
|
||||||
|
}
|
||||||
|
if (currentVolumeData != null) {
|
||||||
|
warning = R.string.volume_alread_saved
|
||||||
}
|
}
|
||||||
binding.textWarning.visibility = if (volumeAction == Action.CREATE && pickMode) {
|
|
||||||
binding.textWarning.text = getString(R.string.choose_existing_volume)
|
|
||||||
binding.buttonAction.isEnabled = false
|
|
||||||
View.VISIBLE
|
|
||||||
} else {
|
} else {
|
||||||
refreshButtonText()
|
warning = R.string.choose_existing_volume
|
||||||
binding.buttonAction.isEnabled = true
|
|
||||||
if (currentVolumeData == null) {
|
|
||||||
View.GONE
|
|
||||||
} else {
|
|
||||||
binding.textWarning.text = getString(R.string.volume_alread_saved)
|
|
||||||
View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
updateWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDirectoryPicked(uri: Uri) {
|
private fun onDirectoryPicked(uri: Uri) {
|
||||||
val path = PathUtils.getFullPathFromTreeUri(uri, requireContext())
|
val path = PathUtils.getFullPathFromTreeUri(uri, requireContext())
|
||||||
if (path != null)
|
if (path == null) {
|
||||||
binding.editVolumeName.setText(path)
|
|
||||||
else
|
|
||||||
CustomAlertDialogBuilder(requireContext(), theme)
|
CustomAlertDialogBuilder(requireContext(), theme)
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(R.string.path_error)
|
.setMessage(R.string.path_error)
|
||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
|
} else {
|
||||||
|
binding.editVolumeName.setText(path)
|
||||||
|
inputViewModel.showEditText = true
|
||||||
|
updateUi(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentVolumePath(): String {
|
private fun getCurrentVolumePath(): String {
|
||||||
@ -243,13 +281,7 @@ class SelectPathFragment: Fragment() {
|
|||||||
if (currentVolumeData == null) { // volume not known
|
if (currentVolumeData == null) { // volume not known
|
||||||
val currentVolumeValue = binding.editVolumeName.text.toString()
|
val currentVolumeValue = binding.editVolumeName.text.toString()
|
||||||
val isHidden = binding.switchHiddenVolume.isChecked
|
val isHidden = binding.switchHiddenVolume.isChecked
|
||||||
if (currentVolumeValue.isEmpty()) {
|
if (isHidden && currentVolumeValue.contains(PathUtils.SEPARATOR)) {
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
if (isHidden) R.string.enter_volume_name else R.string.enter_volume_path,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
} else if (isHidden && currentVolumeValue.contains(PathUtils.SEPARATOR)) {
|
|
||||||
Toast.makeText(requireContext(), R.string.error_slash_in_name, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.error_slash_in_name, Toast.LENGTH_SHORT).show()
|
||||||
} else if (isHidden && volumeAction == Action.CREATE) {
|
} else if (isHidden && volumeAction == Action.CREATE) {
|
||||||
CustomAlertDialogBuilder(requireContext(), theme)
|
CustomAlertDialogBuilder(requireContext(), theme)
|
||||||
@ -263,14 +295,19 @@ class SelectPathFragment: Fragment() {
|
|||||||
onNewVolumeSelected(currentVolumeValue, isHidden)
|
onNewVolumeSelected(currentVolumeValue, isHidden)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(activity as AddVolumeActivity).onVolumeSelected(currentVolumeData!!, true)
|
with (activity as AddVolumeActivity) {
|
||||||
|
if (volumeAction!! == Action.OPEN) {
|
||||||
|
openVolume(currentVolumeData!!, true)
|
||||||
|
} else {
|
||||||
|
onVolumeAdded()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onNewVolumeSelected(currentVolumeValue: String, isHidden: Boolean) {
|
private fun onNewVolumeSelected(currentVolumeValue: String, isHidden: Boolean) {
|
||||||
val volumePath = getCurrentVolumePath()
|
val volumePath = getCurrentVolumePath()
|
||||||
when (volumeAction!!) {
|
if (volumeAction!! == Action.CREATE) {
|
||||||
Action.CREATE -> {
|
|
||||||
val volumeFile = File(volumePath)
|
val volumeFile = File(volumePath)
|
||||||
var goodDirectory = false
|
var goodDirectory = false
|
||||||
if (volumeFile.isFile) {
|
if (volumeFile.isFile) {
|
||||||
@ -285,10 +322,15 @@ class SelectPathFragment: Fragment() {
|
|||||||
errorDirectoryNotWritable(volumePath)
|
errorDirectoryNotWritable(volumePath)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), R.string.dir_not_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.dir_not_empty, Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), R.string.listdir_null_error_msg, Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
requireContext(),
|
||||||
|
R.string.listdir_null_error_msg,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (File(PathUtils.getParentPath(volumePath)).canWrite()) {
|
if (File(PathUtils.getParentPath(volumePath)).canWrite()) {
|
||||||
@ -298,10 +340,13 @@ class SelectPathFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (goodDirectory) {
|
if (goodDirectory) {
|
||||||
(activity as AddVolumeActivity).createVolume(volumePath, isHidden, binding.switchRemember.isChecked)
|
(activity as AddVolumeActivity).createVolume(
|
||||||
|
volumePath,
|
||||||
|
isHidden,
|
||||||
|
binding.switchRemember.isChecked
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
Action.ADD -> {
|
|
||||||
val volumeType = EncryptedVolume.getVolumeType(volumePath)
|
val volumeType = EncryptedVolume.getVolumeType(volumePath)
|
||||||
if (volumeType < 0) {
|
if (volumeType < 0) {
|
||||||
CustomAlertDialogBuilder(requireContext(), theme)
|
CustomAlertDialogBuilder(requireContext(), theme)
|
||||||
@ -313,7 +358,7 @@ class SelectPathFragment: Fragment() {
|
|||||||
val dialog = CustomAlertDialogBuilder(requireContext(), theme)
|
val dialog = CustomAlertDialogBuilder(requireContext(), theme)
|
||||||
.setTitle(R.string.warning)
|
.setTitle(R.string.warning)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.ok) { _, _ -> addVolume(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType) }
|
.setPositiveButton(R.string.ok) { _, _ -> onExistingVolumeSelected(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType) }
|
||||||
if (PathUtils.isPathOnExternalStorage(volumePath, requireContext())) {
|
if (PathUtils.isPathOnExternalStorage(volumePath, requireContext())) {
|
||||||
dialog.setView(
|
dialog.setView(
|
||||||
DialogSdcardErrorBinding.inflate(layoutInflater).apply {
|
DialogSdcardErrorBinding.inflate(layoutInflater).apply {
|
||||||
@ -326,8 +371,7 @@ class SelectPathFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
dialog.show()
|
dialog.show()
|
||||||
} else {
|
} else {
|
||||||
addVolume(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType)
|
onExistingVolumeSelected(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,11 +393,17 @@ class SelectPathFragment: Fragment() {
|
|||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addVolume(volumeName: String, isHidden: Boolean, volumeType: Byte) {
|
private fun onExistingVolumeSelected(volumeName: String, isHidden: Boolean, volumeType: Byte) {
|
||||||
val volumeData = VolumeData(VolumeData.newUuid(), volumeName, isHidden, volumeType)
|
val volumeData = VolumeData(VolumeData.newUuid(), volumeName, isHidden, volumeType)
|
||||||
if (binding.switchRemember.isChecked) {
|
if (binding.switchRemember.isChecked) {
|
||||||
volumeDatabase.saveVolume(volumeData)
|
volumeDatabase.saveVolume(volumeData)
|
||||||
}
|
}
|
||||||
(activity as AddVolumeActivity).onVolumeSelected(volumeData, binding.switchRemember.isChecked)
|
with (activity as AddVolumeActivity) {
|
||||||
|
if (volumeAction!! == Action.OPEN) {
|
||||||
|
openVolume(volumeData, binding.switchRemember.isChecked)
|
||||||
|
} else {
|
||||||
|
onVolumeAdded()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
9
app/src/main/res/drawable/round_button_background.xml
Normal file
9
app/src/main/res/drawable/round_button_background.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/buttonBackgroundColor"/>
|
||||||
|
<corners android:radius="50dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
@ -55,44 +55,24 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginHorizontal="@dimen/volume_operation_horizontal_gap">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_label"
|
android:id="@+id/text_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/volume_path_label"/>
|
android:layout_marginHorizontal="@dimen/volume_operation_horizontal_gap"
|
||||||
|
android:text="@string/volume_path_label"
|
||||||
<LinearLayout
|
android:layout_marginBottom="10dp"/>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/edit_volume_name"
|
android:id="@+id/edit_volume_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0.5"
|
android:layout_marginHorizontal="@dimen/volume_operation_horizontal_gap"
|
||||||
android:inputType="text"
|
android:hint="@string/volume_path_hint"
|
||||||
android:maxLines="1"
|
|
||||||
android:importantForAutofill="no"
|
android:importantForAutofill="no"
|
||||||
android:hint="@string/volume_path_hint"/>
|
android:inputType="textNoSuggestions"
|
||||||
|
android:maxLines="1"
|
||||||
<ImageButton
|
android:visibility="gone" />
|
||||||
android:id="@+id/button_pick_directory"
|
|
||||||
android:layout_width="@dimen/image_button_size"
|
|
||||||
android:layout_height="@dimen/image_button_size"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:background="#00000000"
|
|
||||||
android:src="@drawable/icon_folder"
|
|
||||||
android:contentDescription="@string/pick_directory" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_warning"
|
android:id="@+id/text_warning"
|
||||||
@ -102,12 +82,40 @@
|
|||||||
android:layout_marginHorizontal="@dimen/volume_operation_horizontal_gap"
|
android:layout_marginHorizontal="@dimen/volume_operation_horizontal_gap"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_pick_directory"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
style="@style/RoundButton"
|
||||||
|
android:drawableStart="@drawable/icon_folder_search"
|
||||||
|
android:text="@string/pick_directory"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginBottom="10dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_or"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/or"
|
||||||
|
android:layout_marginBottom="10dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_enter_path"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
style="@style/RoundButton"
|
||||||
|
android:drawableStart="@drawable/icon_edit"
|
||||||
|
android:text="@string/enter_volume_path"
|
||||||
|
android:layout_gravity="center_horizontal"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/switch_remember"
|
android:id="@+id/switch_remember"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/remember_volume"
|
android:text="@string/remember_volume"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
android:layout_gravity="center"/>
|
android:layout_gravity="center"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
@ -117,6 +125,7 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginHorizontal="@dimen/volume_operation_button_horizontal_margin"
|
android:layout_marginHorizontal="@dimen/volume_operation_button_horizontal_margin"
|
||||||
android:layout_marginTop="@dimen/volume_operation_vertical_gap"
|
android:layout_marginTop="@dimen/volume_operation_vertical_gap"
|
||||||
|
android:visibility="gone"
|
||||||
android:text="@string/create_volume" />
|
android:text="@string/create_volume" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -32,8 +32,8 @@
|
|||||||
<string name="storage_perm_denied_msg">إن DroidFS لا يمكنه العمل بدون صلاحبات التخزين.</string>
|
<string name="storage_perm_denied_msg">إن DroidFS لا يمكنه العمل بدون صلاحبات التخزين.</string>
|
||||||
<string name="get_size_failed">لقد فشلت عملية استرداد حجم الملف.</string>
|
<string name="get_size_failed">لقد فشلت عملية استرداد حجم الملف.</string>
|
||||||
<string name="parent_folder">المجلد الأصلي</string>
|
<string name="parent_folder">المجلد الأصلي</string>
|
||||||
<string name="enter_volume_path">رجاءاً أدخل مسار المجلد المشفر</string>
|
<string name="empty_volume_path">رجاءاً أدخل مسار المجلد المشفر</string>
|
||||||
<string name="enter_volume_name">رجاءاً أدخل اسم المجلد المشفر</string>
|
<string name="empty_volume_name">رجاءاً أدخل اسم المجلد المشفر</string>
|
||||||
<string name="external_open">فتح بتطبيق خارجي</string>
|
<string name="external_open">فتح بتطبيق خارجي</string>
|
||||||
<string name="single_delete_confirm">هل أنت متأكد من حذف %s ?</string>
|
<string name="single_delete_confirm">هل أنت متأكد من حذف %s ?</string>
|
||||||
<string name="multiple_delete_confirm">هل أنت متأكد من حذف هذه %s العناصر ?</string>
|
<string name="multiple_delete_confirm">هل أنت متأكد من حذف هذه %s العناصر ?</string>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS kann ohne Speicherberechtigung nicht funktionieren</string>
|
<string name="storage_perm_denied_msg">DroidFS kann ohne Speicherberechtigung nicht funktionieren</string>
|
||||||
<string name="get_size_failed">Fehlgeschlagen beim Abrufen der Dateigröße.</string>
|
<string name="get_size_failed">Fehlgeschlagen beim Abrufen der Dateigröße.</string>
|
||||||
<string name="parent_folder">Übergeordneter Ordner</string>
|
<string name="parent_folder">Übergeordneter Ordner</string>
|
||||||
<string name="enter_volume_path">Bitte geben Sie den Volume-Pfad ein</string>
|
<string name="empty_volume_path">Bitte geben Sie den Volume-Pfad ein</string>
|
||||||
<string name="enter_volume_name">Bitte geben Sie den Datenträgernamen ein</string>
|
<string name="empty_volume_name">Bitte geben Sie den Datenträgernamen ein</string>
|
||||||
<string name="external_open">Öffnen mit externer Anwendung</string>
|
<string name="external_open">Öffnen mit externer Anwendung</string>
|
||||||
<string name="single_delete_confirm">Sind Sie sicher, dass Sie %s löschen wollen?</string>
|
<string name="single_delete_confirm">Sind Sie sicher, dass Sie %s löschen wollen?</string>
|
||||||
<string name="multiple_delete_confirm">Sind Sie sicher, dass Sie diese %s Elemente löschen wollen?</string>
|
<string name="multiple_delete_confirm">Sind Sie sicher, dass Sie diese %s Elemente löschen wollen?</string>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS no puede funcionar sin permisos de almacenamiento.</string>
|
<string name="storage_perm_denied_msg">DroidFS no puede funcionar sin permisos de almacenamiento.</string>
|
||||||
<string name="get_size_failed">No se ha podido recuperar el tamaño del archivo.</string>
|
<string name="get_size_failed">No se ha podido recuperar el tamaño del archivo.</string>
|
||||||
<string name="parent_folder">Carpeta superior</string>
|
<string name="parent_folder">Carpeta superior</string>
|
||||||
<string name="enter_volume_path">Por favor, introduce la ruta del volumen</string>
|
<string name="empty_volume_path">Por favor, introduce la ruta del volumen</string>
|
||||||
<string name="enter_volume_name">Por favor, introduce el nombre del volumen</string>
|
<string name="empty_volume_name">Por favor, introduce el nombre del volumen</string>
|
||||||
<string name="external_open">Abrir con una aplicación externa</string>
|
<string name="external_open">Abrir con una aplicación externa</string>
|
||||||
<string name="single_delete_confirm">¿Estás seguro de que quieres borrar %s ?</string>
|
<string name="single_delete_confirm">¿Estás seguro de que quieres borrar %s ?</string>
|
||||||
<string name="multiple_delete_confirm">¿Estás seguro de que quiere borrar %s objetos?</string>
|
<string name="multiple_delete_confirm">¿Estás seguro de que quiere borrar %s objetos?</string>
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS não pode funcionar sem permissão ao armazenamento.</string>
|
<string name="storage_perm_denied_msg">DroidFS não pode funcionar sem permissão ao armazenamento.</string>
|
||||||
<string name="get_size_failed">Falha na recuperação do tamanho do arquivo.</string>
|
<string name="get_size_failed">Falha na recuperação do tamanho do arquivo.</string>
|
||||||
<string name="parent_folder">Pasta principal</string>
|
<string name="parent_folder">Pasta principal</string>
|
||||||
<string name="enter_volume_path">Por favor, digite a localização do volume</string>
|
<string name="empty_volume_path">Por favor, digite a localização do volume</string>
|
||||||
<string name="enter_volume_name">Por favor, digite o nome do volume</string>
|
<string name="empty_volume_name">Por favor, digite o nome do volume</string>
|
||||||
<string name="external_open">Abrir com app externo</string>
|
<string name="external_open">Abrir com app externo</string>
|
||||||
<string name="single_delete_confirm">Você tem certeza que quer excluir %s?</string>
|
<string name="single_delete_confirm">Você tem certeza que quer excluir %s?</string>
|
||||||
<string name="multiple_delete_confirm">Você realmente deseja excluir estos %s itens?</string>
|
<string name="multiple_delete_confirm">Você realmente deseja excluir estos %s itens?</string>
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS не может работать без разрешения на доступ к хранилищу.</string>
|
<string name="storage_perm_denied_msg">DroidFS не может работать без разрешения на доступ к хранилищу.</string>
|
||||||
<string name="get_size_failed">Невозможно получить размер файла.</string>
|
<string name="get_size_failed">Невозможно получить размер файла.</string>
|
||||||
<string name="parent_folder">Родительская папка</string>
|
<string name="parent_folder">Родительская папка</string>
|
||||||
<string name="enter_volume_path">Введите путь тома</string>
|
<string name="empty_volume_path">Введите путь тома</string>
|
||||||
<string name="enter_volume_name">Введите название тома</string>
|
<string name="empty_volume_name">Введите название тома</string>
|
||||||
<string name="external_open">Открыть внешним приложением</string>
|
<string name="external_open">Открыть внешним приложением</string>
|
||||||
<string name="single_delete_confirm">Удалить %s?</string>
|
<string name="single_delete_confirm">Удалить %s?</string>
|
||||||
<string name="multiple_delete_confirm">Удалить %s элементов?</string>
|
<string name="multiple_delete_confirm">Удалить %s элементов?</string>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS, depolama izinleri olmadan çalışamaz.</string>
|
<string name="storage_perm_denied_msg">DroidFS, depolama izinleri olmadan çalışamaz.</string>
|
||||||
<string name="get_size_failed">Dosya boyutu alınamadı.</string>
|
<string name="get_size_failed">Dosya boyutu alınamadı.</string>
|
||||||
<string name="parent_folder">Ana klasör</string>
|
<string name="parent_folder">Ana klasör</string>
|
||||||
<string name="enter_volume_path">Lütfen birim yolunu girin</string>
|
<string name="empty_volume_path">Lütfen birim yolunu girin</string>
|
||||||
<string name="enter_volume_name">Lütfen birim adını girin</string>
|
<string name="empty_volume_name">Lütfen birim adını girin</string>
|
||||||
<string name="external_open">Harici uygulamayla aç</string>
|
<string name="external_open">Harici uygulamayla aç</string>
|
||||||
<string name="single_delete_confirm">Silmek istediğimizden emin misiniz: %s</string>
|
<string name="single_delete_confirm">Silmek istediğimizden emin misiniz: %s</string>
|
||||||
<string name="multiple_delete_confirm">Bunları silmek istediğinizden emin misiniz: %s</string>
|
<string name="multiple_delete_confirm">Bunları silmek istediğinizden emin misiniz: %s</string>
|
||||||
|
@ -34,8 +34,8 @@
|
|||||||
<string name="storage_perm_denied_msg">没有存储权限时DroidFS无法工作</string>
|
<string name="storage_perm_denied_msg">没有存储权限时DroidFS无法工作</string>
|
||||||
<string name="get_size_failed">无法获取文件的大小</string>
|
<string name="get_size_failed">无法获取文件的大小</string>
|
||||||
<string name="parent_folder">上一级文件夹</string>
|
<string name="parent_folder">上一级文件夹</string>
|
||||||
<string name="enter_volume_path">输入卷的路径</string>
|
<string name="empty_volume_path">输入卷的路径</string>
|
||||||
<string name="enter_volume_name">输入卷的名称</string>
|
<string name="empty_volume_name">输入卷的名称</string>
|
||||||
<string name="external_open">使用外部软件打开</string>
|
<string name="external_open">使用外部软件打开</string>
|
||||||
<string name="single_delete_confirm">确认删除%s?</string>
|
<string name="single_delete_confirm">确认删除%s?</string>
|
||||||
<string name="multiple_delete_confirm">确认删除多个文件:%s</string>
|
<string name="multiple_delete_confirm">确认删除多个文件:%s</string>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
<string name="storage_perm_denied_msg">DroidFS can\'t work without storage permissions.</string>
|
<string name="storage_perm_denied_msg">DroidFS can\'t work without storage permissions.</string>
|
||||||
<string name="get_size_failed">Failed to retrieve file size.</string>
|
<string name="get_size_failed">Failed to retrieve file size.</string>
|
||||||
<string name="parent_folder">Parent Folder</string>
|
<string name="parent_folder">Parent Folder</string>
|
||||||
<string name="enter_volume_path">Please enter the volume path</string>
|
<string name="empty_volume_path">Please enter the volume path</string>
|
||||||
<string name="enter_volume_name">Please enter the volume name</string>
|
<string name="empty_volume_name">Please enter the volume name</string>
|
||||||
<string name="external_open">Open with external app</string>
|
<string name="external_open">Open with external app</string>
|
||||||
<string name="single_delete_confirm">Are you sure you want to delete %s ?</string>
|
<string name="single_delete_confirm">Are you sure you want to delete %s ?</string>
|
||||||
<string name="multiple_delete_confirm">Are you sure you want to delete these %s items ?</string>
|
<string name="multiple_delete_confirm">Are you sure you want to delete these %s items ?</string>
|
||||||
@ -174,7 +174,7 @@
|
|||||||
<string name="seek_seconds_forward">+%d seconds</string>
|
<string name="seek_seconds_forward">+%d seconds</string>
|
||||||
<string name="seek_seconds_backward">-%d seconds</string>
|
<string name="seek_seconds_backward">-%d seconds</string>
|
||||||
<string name="add_volume">Add volume</string>
|
<string name="add_volume">Add volume</string>
|
||||||
<string name="pick_directory">Pick directory</string>
|
<string name="pick_directory">Pick a directory</string>
|
||||||
<string name="volume_alread_saved">Volume already saved</string>
|
<string name="volume_alread_saved">Volume already saved</string>
|
||||||
<string name="open_dialog_title">Opening %s:</string>
|
<string name="open_dialog_title">Opening %s:</string>
|
||||||
<string name="remove">Remove</string>
|
<string name="remove">Remove</string>
|
||||||
@ -289,4 +289,6 @@
|
|||||||
<string name="usf_keep_open_summary">Maintain the app always running in the background to keep volumes open</string>
|
<string name="usf_keep_open_summary">Maintain the app always running in the background to keep volumes open</string>
|
||||||
<string name="gocryptfs_details">Fast, but doesn\'t hide file sizes and directory structure</string>
|
<string name="gocryptfs_details">Fast, but doesn\'t hide file sizes and directory structure</string>
|
||||||
<string name="cryfs_details">Slower, but protects metadata and prevents replacement attacks</string>
|
<string name="cryfs_details">Slower, but protects metadata and prevents replacement attacks</string>
|
||||||
|
<string name="or">or</string>
|
||||||
|
<string name="enter_volume_path">Enter volume path</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<item name="android:statusBarColor">@color/primary</item>
|
<item name="android:statusBarColor">@color/primary</item>
|
||||||
<item name="infoBarBackgroundColor">#181818</item>
|
<item name="infoBarBackgroundColor">#181818</item>
|
||||||
<item name="buttonBackgroundColor">#5B5A5C</item>
|
<item name="buttonBackgroundColor">#5B5A5C</item>
|
||||||
<item name="buttonStyle">@style/DarkButton</item>
|
<item name="buttonStyle">@style/Button</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DarkRed" parent="BaseTheme">
|
<style name="DarkRed" parent="BaseTheme">
|
||||||
@ -35,7 +35,6 @@
|
|||||||
<item name="android:navigationBarColor">@color/black</item>
|
<item name="android:navigationBarColor">@color/black</item>
|
||||||
<item name="infoBarBackgroundColor">@color/black</item>
|
<item name="infoBarBackgroundColor">@color/black</item>
|
||||||
<item name="buttonBackgroundColor">#3B3A3C</item>
|
<item name="buttonBackgroundColor">#3B3A3C</item>
|
||||||
<item name="buttonStyle">@style/BlackButton</item>
|
|
||||||
</style>
|
</style>
|
||||||
<style name="BlackRed" parent="BlackGreen">
|
<style name="BlackRed" parent="BlackGreen">
|
||||||
<item name="colorAccent">@color/red</item>
|
<item name="colorAccent">@color/red</item>
|
||||||
@ -56,11 +55,17 @@
|
|||||||
<item name="colorAccent">@color/pink</item>
|
<item name="colorAccent">@color/pink</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DarkButton" parent="Widget.AppCompat.Button">
|
<style name="Button" parent="Widget.AppCompat.Button">
|
||||||
<item name="android:background">@drawable/button_background</item>
|
<item name="android:background">@drawable/button_background</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="BlackButton" parent="Widget.AppCompat.Button">
|
|
||||||
<item name="android:background">@drawable/button_background</item>
|
<style name="RoundButton" parent="Widget.AppCompat.Button">
|
||||||
|
<item name="android:background">@drawable/round_button_background</item>
|
||||||
|
<item name="textAllCaps">false</item>
|
||||||
|
<item name="android:layout_height">35sp</item>
|
||||||
|
<item name="android:paddingStart">15dp</item>
|
||||||
|
<item name="android:paddingEnd">15dp</item>
|
||||||
|
<item name="android:drawablePadding">5dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="infoBarTextView">
|
<style name="infoBarTextView">
|
||||||
|
Loading…
Reference in New Issue
Block a user