Browse Source

Use New Validator inside ChooseTemplateDialogFragment

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 năm trước cách đây
mục cha
commit
47a4ac4191

+ 120 - 121
app/src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.kt

@@ -1,6 +1,7 @@
 /*
  * Nextcloud - Android Client
  *
+ * SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
  * SPDX-FileCopyrightText: 2023 TSI-mc
  * SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro.brey@nextcloud.com>
  * SPDX-FileCopyrightText: 2019 Chris Narkiewicz <hello@ezaquarii.com>
@@ -10,6 +11,7 @@
  */
 package com.owncloud.android.ui.dialog
 
+import android.annotation.SuppressLint
 import android.app.Dialog
 import android.content.Intent
 import android.os.AsyncTask
@@ -30,6 +32,7 @@ import com.nextcloud.client.di.Injectable
 import com.nextcloud.client.network.ClientFactory
 import com.nextcloud.client.network.ClientFactory.CreationException
 import com.nextcloud.utils.extensions.getParcelableArgument
+import com.nextcloud.utils.fileNameValidator.FileNameValidator
 import com.owncloud.android.MainApp
 import com.owncloud.android.R
 import com.owncloud.android.databinding.ChooseTemplateBinding
@@ -79,12 +82,6 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
     private var positiveButton: MaterialButton? = null
     private var creator: Creator? = null
 
-    enum class Type {
-        DOCUMENT,
-        SPREADSHEET,
-        PRESENTATION
-    }
-
     private var _binding: ChooseTemplateBinding? = null
     val binding get() = _binding!!
 
@@ -92,18 +89,21 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
         super.onStart()
         val alertDialog = dialog as AlertDialog
 
-        val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton
-        viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton)
-
-        val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton
-        viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
+        val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as? MaterialButton
+        negativeButton?.let {
+            viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
+        }
 
-        positiveButton.setOnClickListener(this)
-        positiveButton.isEnabled = false
-        positiveButton.isClickable = false
+        val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as? MaterialButton
+        positiveButton?.let {
+            viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton)
+            positiveButton.setOnClickListener(this)
+            positiveButton.isEnabled = false
+            positiveButton.isClickable = false
+            this.positiveButton = positiveButton
+        }
 
-        this.positiveButton = positiveButton
-        checkEnablingCreateButton()
+        checkFileNameAfterEachType()
     }
 
     override fun onResume() {
@@ -126,10 +126,8 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
 
         fileNames = fileDataStorageManager.getFolderContent(parentFolder, false).map { it.fileName }
 
-        // Inflate the layout for the dialog
         val inflater = requireActivity().layoutInflater
         _binding = ChooseTemplateBinding.inflate(inflater, null, false)
-        val view: View = binding.root
 
         viewThemeUtils.material.colorTextInputLayout(
             binding.filenameContainer
@@ -137,13 +135,9 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
 
         binding.filename.addTextChangedListener(object : TextWatcher {
             override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit
-
-            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
-                // not needed
-            }
-
+            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) = Unit
             override fun afterTextChanged(s: Editable) {
-                checkEnablingCreateButton()
+                checkFileNameAfterEachType()
             }
         })
 
@@ -152,7 +146,7 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
         binding.list.setHasFixedSize(true)
         binding.list.layoutManager = GridLayoutManager(activity, 2)
         adapter = TemplateAdapter(
-            creator!!.mimetype,
+            creator?.mimetype,
             this,
             context,
             currentAccount,
@@ -161,9 +155,8 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
         )
         binding.list.adapter = adapter
 
-        // Build the dialog
         val builder = MaterialAlertDialogBuilder(activity)
-        builder.setView(view)
+            .setView(binding.root)
             .setPositiveButton(R.string.create, null)
             .setNegativeButton(R.string.common_cancel, null)
             .setTitle(title)
@@ -197,6 +190,7 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
         CreateFileFromTemplateTask(this, clientFactory, currentAccount.user, template, path, creator).execute()
     }
 
+    @SuppressLint("NotifyDataSetChanged")
     fun setTemplateList(templateList: TemplateList?) {
         adapter?.setTemplateList(templateList)
         adapter?.notifyDataSetChanged()
@@ -207,9 +201,9 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
     }
 
     private fun onTemplateChosen(template: Template) {
-        adapter!!.setTemplateAsActive(template)
+        adapter?.setTemplateAsActive(template)
         prefillFilenameIfEmpty(template)
-        checkEnablingCreateButton()
+        checkFileNameAfterEachType()
     }
 
     private fun prefillFilenameIfEmpty(template: Template) {
@@ -224,13 +218,16 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
 
     override fun onClick(v: View) {
         val name = binding.filename.text.toString()
-        val path = parentFolder!!.remotePath + name
+        val path = parentFolder?.remotePath + name
+        val selectedTemplate = adapter?.selectedTemplate
 
-        val selectedTemplate = adapter!!.selectedTemplate
+        val errorMessageId: Int? = FileNameValidator.isValid(name)?.messageId
 
         if (selectedTemplate == null) {
             DisplayUtils.showSnackMessage(binding.list, R.string.select_one_template)
-        } else if (name.isEmpty() || name.equals(DOT + selectedTemplate.extension, ignoreCase = true)) {
+        } else if (errorMessageId != null) {
+            DisplayUtils.showSnackMessage(requireActivity(), errorMessageId)
+        } else if (name.equals(DOT + selectedTemplate.extension, ignoreCase = true)) {
             DisplayUtils.showSnackMessage(binding.list, R.string.enter_filename)
         } else if (!name.endsWith(selectedTemplate.extension)) {
             createFromTemplate(selectedTemplate, path + DOT + selectedTemplate.extension)
@@ -239,56 +236,55 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
         }
     }
 
-    private fun checkEnablingCreateButton() {
-        if (positiveButton != null) {
-            val selectedTemplate = adapter!!.selectedTemplate
-            val name = binding.filename.text.toString().trim()
-            val isNameJustExtension = selectedTemplate != null && name.equals(
-                DOT + selectedTemplate.extension,
-                ignoreCase = true
-            )
-            val isNameEmpty = name.isEmpty() || isNameJustExtension
-            val state = selectedTemplate != null && !isNameEmpty && !fileNames.contains(name)
-
-            positiveButton?.isEnabled = state
-            positiveButton?.isClickable = state
-            binding.filenameContainer.isErrorEnabled = !state
-
-            if (!state) {
-                if (isNameEmpty) {
-                    binding.filenameContainer.error = getText(R.string.filename_empty)
-                } else {
-                    binding.filenameContainer.error = getText(R.string.file_already_exists)
-                }
-            }
+    private fun checkFileNameAfterEachType() {
+        if (positiveButton == null) return
+
+        val selectedTemplate = adapter?.selectedTemplate
+        val name = binding.filename.text.toString().trim()
+        val isNameJustExtension = selectedTemplate != null && name.equals(
+            DOT + selectedTemplate.extension,
+            ignoreCase = true
+        )
+        val errorMessageId: Int? = FileNameValidator.isValid(name)?.messageId
+        val error = when {
+            name.isEmpty() || isNameJustExtension -> null
+            name[0] == '.' -> R.string.hidden_file_name_warning
+            errorMessageId != null -> errorMessageId
+            fileNames.contains(name) -> R.string.file_already_exists
+            else -> null
+        }
+
+        positiveButton?.isEnabled = (error == null)
+        positiveButton?.isClickable = (error == null)
+        binding.filenameContainer.isErrorEnabled = (error != null)
+        if (error != null) {
+            binding.filenameContainer.error = getText(error)
         }
     }
 
-    @Suppress("LongParameterList") // legacy code
+    @Suppress("LongParameterList", "DEPRECATION")
     private class CreateFileFromTemplateTask(
         chooseTemplateDialogFragment: ChooseTemplateDialogFragment,
         private val clientFactory: ClientFactory?,
-        user: User,
-        template: Template,
-        path: String,
-        creator: Creator?
-    ) : AsyncTask<Void, Void, String>() {
-        private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment>
-        private val template: Template
-        private val path: String
+        private val user: User,
+        private val template: Template,
+        private val path: String,
         private val creator: Creator?
-        private val user: User
+    ) : AsyncTask<Void, Void, String>() {
+        private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment> =
+            WeakReference(chooseTemplateDialogFragment)
         private var file: OCFile? = null
 
+        @Deprecated("Deprecated in Java")
         @Suppress("ReturnCount") // legacy code
         override fun doInBackground(vararg params: Void): String {
             return try {
-                val client = clientFactory!!.create(user)
+                val client = clientFactory?.create(user) ?: return ""
                 val nextcloudClient = clientFactory.createNextcloudClient(user)
                 val result = DirectEditingCreateFileRemoteOperation(
                     path,
-                    creator!!.editor,
-                    creator.id,
+                    creator?.editor,
+                    creator?.id,
                     template.title
                 ).execute(nextcloudClient)
                 if (!result.isSuccess) {
@@ -316,51 +312,51 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
             }
         }
 
+        @Deprecated("Deprecated in Java")
         override fun onPostExecute(url: String) {
             val fragment = chooseTemplateDialogFragmentWeakReference.get()
-            if (fragment != null && fragment.isAdded) {
-                if (url.isEmpty()) {
-                    DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_creating_file_from_template)
-                } else {
-                    val editorWebView = Intent(MainApp.getAppContext(), TextEditorWebView::class.java)
-                    editorWebView.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Text")
-                    editorWebView.putExtra(ExternalSiteWebView.EXTRA_URL, url)
-                    editorWebView.putExtra(ExternalSiteWebView.EXTRA_FILE, file)
-                    editorWebView.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false)
-                    fragment.startActivity(editorWebView)
-                    fragment.dismiss()
-                }
-            } else {
+            if (fragment == null || !fragment.isAdded) {
                 Log_OC.e(TAG, "Error creating file from template!")
+                return
             }
-        }
 
-        init {
-            chooseTemplateDialogFragmentWeakReference = WeakReference(chooseTemplateDialogFragment)
-            this.template = template
-            this.path = path
-            this.creator = creator
-            this.user = user
+            if (url.isEmpty()) {
+                DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_creating_file_from_template)
+                return
+            }
+
+            val editorWebView = Intent(MainApp.getAppContext(), TextEditorWebView::class.java).apply {
+                putExtra(ExternalSiteWebView.EXTRA_TITLE, "Text")
+                putExtra(ExternalSiteWebView.EXTRA_URL, url)
+                putExtra(ExternalSiteWebView.EXTRA_FILE, file)
+                putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false)
+            }
+
+            fragment.run {
+                startActivity(editorWebView)
+                dismiss()
+            }
         }
     }
 
+    @Suppress("DEPRECATION")
     private class FetchTemplateTask(
         chooseTemplateDialogFragment: ChooseTemplateDialogFragment,
         private val clientFactory: ClientFactory?,
         private val user: User,
-        creator: Creator?
-    ) : AsyncTask<Void, Void, TemplateList>() {
-        private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment>
         private val creator: Creator?
+    ) : AsyncTask<Void, Void, TemplateList>() {
+        private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment> =
+            WeakReference(chooseTemplateDialogFragment)
 
+        @Deprecated("Deprecated in Java")
         override fun doInBackground(vararg voids: Void): TemplateList {
             return try {
-                val client = clientFactory!!.createNextcloudClient(user)
+                val client = clientFactory?.createNextcloudClient(user) ?: return TemplateList()
                 val result = DirectEditingObtainListOfTemplatesRemoteOperation(
-                    creator!!.editor,
-                    creator.id
-                )
-                    .execute(client)
+                    creator?.editor,
+                    creator?.id
+                ).execute(client)
                 if (!result.isSuccess) {
                     TemplateList()
                 } else {
@@ -372,30 +368,31 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
             }
         }
 
+        @Deprecated("Deprecated in Java")
         override fun onPostExecute(templateList: TemplateList) {
             val fragment = chooseTemplateDialogFragmentWeakReference.get()
-            if (fragment != null && fragment.isAdded) {
-                if (templateList.templates.isEmpty()) {
-                    DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates)
-                } else {
-                    if (templateList.templates.size == SINGLE_TEMPLATE) {
-                        fragment.onTemplateChosen(templateList.templates.values.iterator().next())
-                        fragment.binding.list.visibility = View.GONE
-                    } else {
-                        val name = DOT + templateList.templates.values.iterator().next().extension
-                        fragment.binding.filename.setText(name)
-                        fragment.binding.helperText.visibility = View.VISIBLE
-                    }
-                    fragment.setTemplateList(templateList)
-                }
-            } else {
+            if (fragment == null || !fragment.isAdded) {
                 Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!")
+                return
             }
-        }
 
-        init {
-            chooseTemplateDialogFragmentWeakReference = WeakReference(chooseTemplateDialogFragment)
-            this.creator = creator
+            if (templateList.templates.isEmpty()) {
+                DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates)
+                return
+            }
+
+            fragment.run {
+                if (templateList.templates.size == SINGLE_TEMPLATE) {
+                    onTemplateChosen(templateList.templates.values.iterator().next())
+                    binding.list.visibility = View.GONE
+                } else {
+                    val name = DOT + templateList.templates.values.iterator().next().extension
+                    binding.filename.setText(name)
+                    binding.helperText.visibility = View.VISIBLE
+                }
+
+                setTemplateList(templateList)
+            }
         }
     }
 
@@ -409,13 +406,15 @@ class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, Tem
 
         @JvmStatic
         fun newInstance(parentFolder: OCFile?, creator: Creator?, headline: String?): ChooseTemplateDialogFragment {
-            val frag = ChooseTemplateDialogFragment()
-            val args = Bundle()
-            args.putParcelable(ARG_PARENT_FOLDER, parentFolder)
-            args.putParcelable(ARG_CREATOR, creator)
-            args.putString(ARG_HEADLINE, headline)
-            frag.arguments = args
-            return frag
+            val bundle = Bundle().apply {
+                putParcelable(ARG_PARENT_FOLDER, parentFolder)
+                putParcelable(ARG_CREATOR, creator)
+                putString(ARG_HEADLINE, headline)
+            }
+
+            return ChooseTemplateDialogFragment().apply {
+                arguments = bundle
+            }
         }
     }
 }