Convert to Kotlin

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-07-04 13:55:13 +02:00 committed by Alper Öztürk
parent 34055bbfea
commit 5c6439f111
5 changed files with 219 additions and 236 deletions

View file

@ -48,7 +48,10 @@ object FileNameValidator {
} }
if (capability.forbiddenFilenames.isTrue && if (capability.forbiddenFilenames.isTrue &&
(reservedWindowsNames.contains(name.uppercase()) || reservedWindowsNames.contains(name.removeFileExtension().uppercase())) (
reservedWindowsNames.contains(name.uppercase()) ||
reservedWindowsNames.contains(name.removeFileExtension().uppercase())
)
) { ) {
return context.getString(R.string.file_name_validator_error_reserved_names) return context.getString(R.string.file_name_validator_error_reserved_names)
} }
@ -60,6 +63,7 @@ object FileNameValidator {
return null return null
} }
@Suppress("ReturnCount")
fun checkPath(folderPath: String, filePaths: List<String>, capability: OCCapability, context: Context): Boolean { fun checkPath(folderPath: String, filePaths: List<String>, capability: OCCapability, context: Context): Boolean {
val folderPaths = folderPath.split("/", "\\") val folderPaths = folderPath.split("/", "\\")
@ -78,6 +82,7 @@ object FileNameValidator {
return true return true
} }
@Suppress("ReturnCount")
private fun checkInvalidCharacters(name: String, capability: OCCapability, context: Context): String? { private fun checkInvalidCharacters(name: String, capability: OCCapability, context: Context): String? {
if (capability.forbiddenFilenameCharacters.isFalse) return null if (capability.forbiddenFilenameCharacters.isFalse) return null

View file

@ -154,6 +154,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
listener?.conflictDecisionMade(decision) listener?.conflictDecisionMade(decision)
} }
@Suppress("ReturnCount")
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
if (account == null) { if (account == null) {

View file

@ -462,7 +462,6 @@ open class FolderPickerActivity :
Handler(Looper.getMainLooper()).postDelayed({ Handler(Looper.getMainLooper()).postDelayed({
setResult(RESULT_CANCELED, resultData) setResult(RESULT_CANCELED, resultData)
finish() finish()
}, 1000L) }, 1000L)
return return
} }

View file

@ -8,61 +8,181 @@
* SPDX-FileCopyrightText: 2014 David A. Velasco <dvelasco@solidgear.es> * SPDX-FileCopyrightText: 2014 David A. Velasco <dvelasco@solidgear.es>
* SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only) * SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
*/ */
package com.owncloud.android.ui.dialog; package com.owncloud.android.ui.dialog
import android.app.Dialog; import android.app.Dialog
import android.content.DialogInterface; import android.content.DialogInterface
import android.os.Bundle; import android.os.Bundle
import android.text.Editable; import android.text.Editable
import android.text.TextWatcher; import android.text.TextWatcher
import android.view.LayoutInflater; import android.view.View
import android.view.View; import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.common.collect.Sets; import com.google.common.collect.Sets
import com.nextcloud.client.account.CurrentAccountProvider; import com.nextcloud.client.account.CurrentAccountProvider
import com.nextcloud.client.di.Injectable; import com.nextcloud.client.di.Injectable
import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.fileNameValidator.FileNameValidator; import com.nextcloud.utils.fileNameValidator.FileNameValidator.isFileHidden
import com.owncloud.android.R; import com.nextcloud.utils.fileNameValidator.FileNameValidator.isValid
import com.owncloud.android.databinding.EditBoxDialogBinding; import com.owncloud.android.R
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.databinding.EditBoxDialogBinding
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.lib.resources.status.OCCapability
import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.ui.activity.ComponentsGetter
import com.owncloud.android.utils.KeyboardUtils; import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.theme.ViewThemeUtils; import com.owncloud.android.utils.KeyboardUtils
import com.owncloud.android.utils.theme.ViewThemeUtils
import java.util.List; import javax.inject.Inject
import java.util.Set;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
/** /**
* Dialog to input a new name for an {@link OCFile} being renamed. * Dialog to input a new name for an [OCFile] being renamed.
* Triggers the rename operation. * Triggers the rename operation.
*/ */
public class RenameFileDialogFragment class RenameFileDialogFragment : DialogFragment(), DialogInterface.OnClickListener, TextWatcher, Injectable {
extends DialogFragment implements DialogInterface.OnClickListener, TextWatcher, Injectable { @Inject
lateinit var viewThemeUtils: ViewThemeUtils
private static final String ARG_TARGET_FILE = "TARGET_FILE"; @Inject
private static final String ARG_PARENT_FOLDER = "PARENT_FOLDER"; lateinit var fileDataStorageManager: FileDataStorageManager
@Inject ViewThemeUtils viewThemeUtils; @Inject
@Inject FileDataStorageManager fileDataStorageManager; lateinit var keyboardUtils: KeyboardUtils
@Inject KeyboardUtils keyboardUtils;
@Inject CurrentAccountProvider currentAccount;
private EditBoxDialogBinding binding; @Inject
private OCFile mTargetFile; lateinit var currentAccount: CurrentAccountProvider
private MaterialButton positiveButton;
private Set<String> fileNames; private lateinit var binding: EditBoxDialogBinding
private var mTargetFile: OCFile? = null
private var positiveButton: MaterialButton? = null
private var fileNames: MutableSet<String>? = null
override fun onStart() {
super.onStart()
initAlertDialog()
}
override fun onResume() {
super.onResume()
keyboardUtils.showKeyboardForEditText(requireDialog().window, binding.userInput)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
mTargetFile = requireArguments().getParcelableArgument(ARG_TARGET_FILE, OCFile::class.java)
val inflater = requireActivity().layoutInflater
binding = EditBoxDialogBinding.inflate(inflater, null, false)
val currentName = mTargetFile?.fileName
binding.userInput.setText(currentName)
viewThemeUtils.material.colorTextInputLayout(binding.userInputContainer)
val extensionStart = if (mTargetFile?.isFolder == true) -1 else currentName?.lastIndexOf('.')
val selectionEnd = if ((extensionStart ?: -1) >= 0) extensionStart else currentName?.length
if (selectionEnd != null) {
binding.userInput.setSelection(0, selectionEnd)
}
val parentFolder = arguments.getParcelableArgument(ARG_PARENT_FOLDER, OCFile::class.java)
val folderContent = fileDataStorageManager.getFolderContent(parentFolder, false)
fileNames = Sets.newHashSetWithExpectedSize(folderContent.size)
for (file in folderContent) {
fileNames?.add(file.fileName)
}
binding.userInput.addTextChangedListener(this)
val builder = buildMaterialAlertDialog(binding.root)
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInputContainer.context, builder)
return builder.create()
}
private fun buildMaterialAlertDialog(view: View): MaterialAlertDialogBuilder {
val builder = MaterialAlertDialogBuilder(requireActivity())
builder
.setView(view)
.setPositiveButton(R.string.file_rename, this)
.setNegativeButton(R.string.common_cancel, this)
.setTitle(R.string.rename_dialog_title)
return builder
}
private fun initAlertDialog() {
val alertDialog = dialog as AlertDialog?
if (alertDialog != null) {
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton
val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton
positiveButton?.let {
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(it)
}
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
}
}
private val oCCapability: OCCapability
get() = fileDataStorageManager.getCapability(currentAccount.user.accountName)
override fun onClick(dialog: DialogInterface, which: Int) {
if (which == AlertDialog.BUTTON_POSITIVE) {
var newFileName = ""
if (binding.userInput.text != null) {
newFileName = binding.userInput.text.toString().trim { it <= ' ' }
}
val errorMessage = isValid(newFileName, oCCapability, requireContext(), null)
if (errorMessage != null) {
DisplayUtils.showSnackMessage(requireActivity(), errorMessage)
return
}
if (requireActivity() is ComponentsGetter) {
val componentsGetter = requireActivity() as ComponentsGetter
componentsGetter.getFileOperationsHelper().renameFile(mTargetFile, newFileName)
}
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit
/**
* When user enters a hidden file name, the 'hidden file' message is shown.
* Otherwise, the message is ensured to be hidden.
*/
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
var newFileName = ""
if (binding.userInput.text != null) {
newFileName = binding.userInput.text.toString().trim { it <= ' ' }
}
val errorMessage = isValid(newFileName, oCCapability, requireContext(), fileNames)
if (isFileHidden(newFileName)) {
binding.userInputContainer.error = getText(R.string.hidden_file_name_warning)
} else if (errorMessage != null) {
binding.userInputContainer.error = errorMessage
positiveButton?.isEnabled = false
} else if (binding.userInputContainer.error != null) {
binding.userInputContainer.error = null
// Called to remove extra padding
binding.userInputContainer.isErrorEnabled = false
positiveButton?.isEnabled = true
}
}
override fun afterTextChanged(s: Editable) = Unit
companion object {
private const val ARG_TARGET_FILE = "TARGET_FILE"
private const val ARG_PARENT_FOLDER = "PARENT_FOLDER"
/** /**
* Public factory method to create new RenameFileDialogFragment instances. * Public factory method to create new RenameFileDialogFragment instances.
@ -70,152 +190,16 @@ public class RenameFileDialogFragment
* @param file File to rename. * @param file File to rename.
* @return Dialog ready to show. * @return Dialog ready to show.
*/ */
public static RenameFileDialogFragment newInstance(OCFile file, OCFile parentFolder) { @JvmStatic
RenameFileDialogFragment frag = new RenameFileDialogFragment(); fun newInstance(file: OCFile?, parentFolder: OCFile?): RenameFileDialogFragment {
Bundle args = new Bundle(); val bundle = Bundle().apply {
args.putParcelable(ARG_TARGET_FILE, file); putParcelable(ARG_TARGET_FILE, file)
args.putParcelable(ARG_PARENT_FOLDER, parentFolder); putParcelable(ARG_PARENT_FOLDER, parentFolder)
frag.setArguments(args);
return frag;
} }
@Override return RenameFileDialogFragment().apply {
public void onStart() { arguments = bundle
super.onStart();
initAlertDialog();
}
@Override
public void onResume() {
super.onResume();
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mTargetFile = BundleExtensionsKt.getParcelableArgument(requireArguments(), ARG_TARGET_FILE, OCFile.class);
// Inflate the layout for the dialog
LayoutInflater inflater = requireActivity().getLayoutInflater();
binding = EditBoxDialogBinding.inflate(inflater, null, false);
View view = binding.getRoot();
// Setup layout
String currentName = mTargetFile.getFileName();
binding.userInput.setText(currentName);
viewThemeUtils.material.colorTextInputLayout(binding.userInputContainer);
int extensionStart = mTargetFile.isFolder() ? -1 : currentName.lastIndexOf('.');
int selectionEnd = extensionStart >= 0 ? extensionStart : currentName.length();
binding.userInput.setSelection(0, selectionEnd);
OCFile parentFolder = BundleExtensionsKt.getParcelableArgument(getArguments(), ARG_PARENT_FOLDER, OCFile.class);
List<OCFile> folderContent = fileDataStorageManager.getFolderContent(parentFolder, false);
fileNames = Sets.newHashSetWithExpectedSize(folderContent.size());
for (OCFile file : folderContent) {
fileNames.add(file.getFileName());
}
// Add TextChangedListener to handle showing/hiding the input warning message
binding.userInput.addTextChangedListener(this);
// Build the dialog
MaterialAlertDialogBuilder builder = buildMaterialAlertDialog(view);
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInputContainer.getContext(), builder);
return builder.create();
}
private MaterialAlertDialogBuilder buildMaterialAlertDialog(View view) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
builder
.setView(view)
.setPositiveButton(R.string.file_rename, this)
.setNegativeButton(R.string.common_cancel, this)
.setTitle(R.string.rename_dialog_title);
return builder;
}
private void initAlertDialog() {
AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog != null) {
positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
}
}
private OCCapability getOCCapability() {
return fileDataStorageManager.getCapability(currentAccount.getUser().getAccountName());
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
String newFileName = "";
if (binding.userInput.getText() != null) {
newFileName = binding.userInput.getText().toString().trim();
}
String errorMessage = FileNameValidator.INSTANCE.isValid(newFileName, getOCCapability(), requireContext(), null);
if (errorMessage != null) {
DisplayUtils.showSnackMessage(requireActivity(), errorMessage);
return;
}
if (requireActivity() instanceof ComponentsGetter componentsGetter) {
componentsGetter.getFileOperationsHelper().renameFile(mTargetFile, newFileName);
} }
} }
} }
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
/**
* When user enters a hidden file name, the 'hidden file' message is shown.
* Otherwise, the message is ensured to be hidden.
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String newFileName = "";
if (binding.userInput.getText() != null) {
newFileName = binding.userInput.getText().toString().trim();
}
String errorMessage = FileNameValidator.INSTANCE.isValid(newFileName, getOCCapability(), requireContext(), fileNames);
if (FileNameValidator.INSTANCE.isFileHidden(newFileName)) {
binding.userInputContainer.setError(getText(R.string.hidden_file_name_warning));
} else if (errorMessage != null) {
binding.userInputContainer.setError(errorMessage);
positiveButton.setEnabled(false);
} else if (binding.userInputContainer.getError() != null) {
binding.userInputContainer.setError(null);
// Called to remove extra padding
binding.userInputContainer.setErrorEnabled(false);
positiveButton.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
} }

View file

@ -5,122 +5,116 @@
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH * SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/ */
package com.owncloud.android.ui.dialog; package com.owncloud.android.ui.dialog
import android.app.Dialog; import android.app.Dialog
import android.content.DialogInterface; import android.content.DialogInterface
import android.os.Bundle; import android.os.Bundle
import android.text.TextUtils; import android.text.TextUtils
import android.view.LayoutInflater; import android.view.View
import android.view.View; import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.client.di.Injectable; import com.nextcloud.client.di.Injectable
import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.extensions.getParcelableArgument
import com.owncloud.android.R; import com.owncloud.android.R
import com.owncloud.android.databinding.EditBoxDialogBinding; import com.owncloud.android.databinding.EditBoxDialogBinding
import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.OCShare
import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.ui.activity.ComponentsGetter
import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.KeyboardUtils; import com.owncloud.android.utils.KeyboardUtils
import com.owncloud.android.utils.theme.ViewThemeUtils; import com.owncloud.android.utils.theme.ViewThemeUtils
import javax.inject.Inject
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
/** /**
* Dialog to rename a public share. * Dialog to rename a public share.
*/ */
public class RenamePublicShareDialogFragment class RenamePublicShareDialogFragment : DialogFragment(), DialogInterface.OnClickListener, Injectable {
extends DialogFragment implements DialogInterface.OnClickListener, Injectable { @Inject
lateinit var viewThemeUtils: ViewThemeUtils
private static final String ARG_PUBLIC_SHARE = "PUBLIC_SHARE"; @Inject
lateinit var keyboardUtils: KeyboardUtils
@Inject ViewThemeUtils viewThemeUtils; private lateinit var binding: EditBoxDialogBinding
@Inject KeyboardUtils keyboardUtils; private var publicShare: OCShare? = null
private EditBoxDialogBinding binding; override fun onStart() {
private OCShare publicShare; super.onStart()
public static RenamePublicShareDialogFragment newInstance(OCShare share) { val alertDialog = dialog as AlertDialog? ?: return
RenamePublicShareDialogFragment frag = new RenamePublicShareDialogFragment();
Bundle args = new Bundle(); val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as? MaterialButton
args.putParcelable(ARG_PUBLIC_SHARE, share); val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as? MaterialButton
frag.setArguments(args);
return frag; positiveButton?.let {
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton)
} }
@Override negativeButton?.let {
public void onStart() { viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
super.onStart();
AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog != null) {
MaterialButton positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
} }
} }
@Override override fun onResume() {
public void onResume() { super.onResume()
super.onResume(); keyboardUtils.showKeyboardForEditText(requireDialog().window, binding.userInput)
keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.userInput);
} }
@NonNull override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@Override publicShare = requireArguments().getParcelableArgument(ARG_PUBLIC_SHARE, OCShare::class.java)
public Dialog onCreateDialog(Bundle savedInstanceState) {
publicShare = BundleExtensionsKt.getParcelableArgument(requireArguments(), ARG_PUBLIC_SHARE, OCShare.class);
// Inflate the layout for the dialog val inflater = requireActivity().layoutInflater
LayoutInflater inflater = requireActivity().getLayoutInflater(); binding = EditBoxDialogBinding.inflate(inflater, null, false)
binding = EditBoxDialogBinding.inflate(inflater, null, false); val view: View = binding.root
View view = binding.getRoot();
// Setup layout viewThemeUtils.material.colorTextInputLayout(binding.userInputContainer)
viewThemeUtils.material.colorTextInputLayout(binding.userInputContainer); binding.userInput.setText(publicShare?.label)
binding.userInput.setText(publicShare.getLabel());
// Build the dialog val builder = MaterialAlertDialogBuilder(view.context)
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(view.getContext()); .setView(view)
builder.setView(view)
.setPositiveButton(R.string.file_rename, this) .setPositiveButton(R.string.file_rename, this)
.setNegativeButton(R.string.common_cancel, this) .setNegativeButton(R.string.common_cancel, this)
.setTitle(R.string.public_share_name); .setTitle(R.string.public_share_name)
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInput.getContext(), builder); viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInput.context, builder)
return builder.create(); return builder.create()
} }
@Override override fun onClick(dialog: DialogInterface, which: Int) {
public void onClick(DialogInterface dialog, int which) { when (which) {
if (which == AlertDialog.BUTTON_POSITIVE) { AlertDialog.BUTTON_POSITIVE -> {
String newName = ""; var newName = ""
if (binding.userInput.getText() != null) { if (binding.userInput.text != null) {
newName = binding.userInput.getText().toString().trim(); newName = binding.userInput.text.toString().trim { it <= ' ' }
} }
if (TextUtils.isEmpty(newName)) { if (TextUtils.isEmpty(newName)) {
DisplayUtils.showSnackMessage(requireActivity(), R.string.label_empty); DisplayUtils.showSnackMessage(requireActivity(), R.string.label_empty)
return; return
} }
((ComponentsGetter) requireActivity()).getFileOperationsHelper().setLabelToPublicShare(publicShare, (requireActivity() as ComponentsGetter).fileOperationsHelper.setLabelToPublicShare(
newName); publicShare,
newName
)
}
} }
} }
@Override companion object {
public void onDestroyView() { private const val ARG_PUBLIC_SHARE = "PUBLIC_SHARE"
super.onDestroyView();
binding = null; fun newInstance(share: OCShare?): RenamePublicShareDialogFragment {
val bundle = Bundle().apply {
putParcelable(ARG_PUBLIC_SHARE, share)
}
return RenamePublicShareDialogFragment().apply {
arguments = bundle
}
}
} }
} }