瀏覽代碼

Merge pull request #12047 from nextcloud/feature/use-m3-SharePasswordDialogFragment

Use Material Design 3 share password dialog fragment
Andy Scherzinger 1 年之前
父節點
當前提交
c52bad82f0

二進制
app/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testEnforcedPasswordDialog.png


二進制
app/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testOptionalPasswordDialog.png


+ 0 - 227
app/src/main/java/com/owncloud/android/ui/dialog/SharePasswordDialogFragment.java

@@ -1,227 +0,0 @@
-/*
- *   ownCloud Android client application
- *
- *   @author masensio
- *   @author Andy Scherzinger
- *   Copyright (C) 2015 ownCloud GmbH.
- *   Copyright (C) 2018 Andy Scherzinger
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.dialog;
-
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.nextcloud.client.di.Injectable;
-import com.owncloud.android.R;
-import com.owncloud.android.databinding.PasswordDialogBinding;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.lib.resources.shares.OCShare;
-import com.owncloud.android.ui.activity.FileActivity;
-import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.KeyboardUtils;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.DialogFragment;
-
-/**
- * Dialog to input the password for sharing a file/folder.
- * <p>
- * Triggers the share when the password is introduced.
- */
-public class SharePasswordDialogFragment extends DialogFragment implements DialogInterface.OnClickListener, Injectable {
-
-    private static final String ARG_FILE = "FILE";
-    private static final String ARG_SHARE = "SHARE";
-    private static final String ARG_CREATE_SHARE = "CREATE_SHARE";
-    private static final String ARG_ASK_FOR_PASSWORD = "ASK_FOR_PASSWORD";
-    public static final String PASSWORD_FRAGMENT = "PASSWORD_FRAGMENT";
-
-    @Inject ViewThemeUtils viewThemeUtils;
-    @Inject KeyboardUtils keyboardUtils;
-
-    private PasswordDialogBinding binding;
-    private OCFile file;
-    private OCShare share;
-    private boolean createShare;
-    private boolean askForPassword;
-
-    @Override
-    public void onStart() {
-        super.onStart();
-
-        AlertDialog alertDialog = (AlertDialog) getDialog();
-        if (alertDialog != null) {
-            viewThemeUtils.platform.colorTextButtons(alertDialog.getButton(AlertDialog.BUTTON_POSITIVE),
-                                                     alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE));
-            viewThemeUtils.platform.colorTextButtons(getResources().getColor(R.color.highlight_textColor_Warning),
-                                                     alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
-
-            alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
-                String password = binding.sharePassword.getText().toString();
-
-                if (!askForPassword && TextUtils.isEmpty(password)) {
-                    DisplayUtils.showSnackMessage(binding.getRoot(), R.string.share_link_empty_password);
-                    return;
-                }
-
-                if (share == null) {
-                    setPassword(createShare, file, password);
-                } else {
-                    setPassword(share, password);
-                }
-
-                alertDialog.dismiss();
-            });
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        keyboardUtils.showKeyboardForEditText(requireDialog().getWindow(), binding.sharePassword);
-    }
-
-    /**
-     * Public factory method to create new SharePasswordDialogFragment instances.
-     *
-     * @param file        OCFile bound to the public share that which password will be set or updated
-     * @param createShare When 'true', the request for password will be followed by the creation of a new public link;
-     *                    when 'false', a public share is assumed to exist, and the password is bound to it.
-     * @return Dialog ready to show.
-     */
-    public static SharePasswordDialogFragment newInstance(OCFile file, boolean createShare, boolean askForPassword) {
-        SharePasswordDialogFragment frag = new SharePasswordDialogFragment();
-        Bundle args = new Bundle();
-        args.putParcelable(ARG_FILE, file);
-        args.putBoolean(ARG_CREATE_SHARE, createShare);
-        args.putBoolean(ARG_ASK_FOR_PASSWORD, askForPassword);
-        frag.setArguments(args);
-        return frag;
-    }
-
-    /**
-     * Public factory method to create new SharePasswordDialogFragment instances.
-     *
-     * @param share OCFile bound to the public share that which password will be set or updated
-     * @return Dialog ready to show.
-     */
-    public static SharePasswordDialogFragment newInstance(OCShare share, boolean askForPassword) {
-        SharePasswordDialogFragment frag = new SharePasswordDialogFragment();
-        Bundle args = new Bundle();
-        args.putParcelable(ARG_SHARE, share);
-        args.putBoolean(ARG_ASK_FOR_PASSWORD, askForPassword);
-        frag.setArguments(args);
-        return frag;
-    }
-
-    /**
-     * Public factory method to create new SharePasswordDialogFragment instances.
-     *
-     * @param share OCFile bound to the public share that which password will be set or updated
-     * @return Dialog ready to show.
-     */
-    public static SharePasswordDialogFragment newInstance(OCShare share) {
-        SharePasswordDialogFragment frag = new SharePasswordDialogFragment();
-        Bundle args = new Bundle();
-        args.putParcelable(ARG_SHARE, share);
-        frag.setArguments(args);
-        return frag;
-    }
-
-    @NonNull
-    @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        file = getArguments().getParcelable(ARG_FILE);
-        share = getArguments().getParcelable(ARG_SHARE);
-        createShare = getArguments().getBoolean(ARG_CREATE_SHARE, false);
-        askForPassword = getArguments().getBoolean(ARG_ASK_FOR_PASSWORD, false);
-
-        // Inflate the layout for the dialog
-        LayoutInflater inflater = requireActivity().getLayoutInflater();
-        binding = PasswordDialogBinding.inflate(inflater, null, false);
-        View view = binding.getRoot();
-
-        // Setup layout
-        binding.sharePassword.setText("");
-        viewThemeUtils.material.colorTextInputLayout(binding.sharePasswordContainer);
-
-        int negativeButtonCaption;
-        int title;
-        if (askForPassword) {
-            title = R.string.share_link_optional_password_title;
-            negativeButtonCaption = R.string.common_skip;
-        } else {
-            title = R.string.share_link_password_title;
-            negativeButtonCaption = R.string.common_cancel;
-        }
-
-        // Build the dialog
-        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(view.getContext());
-
-        builder.setView(view)
-            .setPositiveButton(R.string.common_ok, null)
-            .setNegativeButton(negativeButtonCaption, this)
-            .setNeutralButton(R.string.common_delete, this)
-            .setTitle(title);
-
-        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(view.getContext(), builder);
-
-        return builder.create();
-    }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        if (which == AlertDialog.BUTTON_NEUTRAL) {
-            if (share == null) {
-                setPassword(createShare, file, null);
-            } else {
-                setPassword(share, null);
-            }
-        } else if (which == AlertDialog.BUTTON_NEGATIVE && askForPassword) {
-            if (share == null) {
-                setPassword(createShare, file, null);
-            } else {
-                setPassword(share, null);
-            }
-        }
-    }
-
-    private void setPassword(boolean createShare, OCFile file, String password) {
-        if (createShare) {
-            ((FileActivity) getActivity()).getFileOperationsHelper().shareFileViaPublicShare(file, password);
-        } else {
-            ((FileActivity) getActivity()).getFileOperationsHelper().setPasswordToShare(share, password);
-        }
-    }
-
-    private void setPassword(OCShare share, String password) {
-        ((FileActivity) getActivity()).getFileOperationsHelper().setPasswordToShare(share, password);
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        binding = null;
-    }
-}

+ 250 - 0
app/src/main/java/com/owncloud/android/ui/dialog/SharePasswordDialogFragment.kt

@@ -0,0 +1,250 @@
+/*
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author Andy Scherzinger
+ *   Copyright (C) 2015 ownCloud GmbH.
+ *   Copyright (C) 2018 Andy Scherzinger
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.dialog
+
+import android.app.Dialog
+import android.content.DialogInterface
+import android.os.Build
+import android.os.Bundle
+import android.text.TextUtils
+import androidx.appcompat.app.AlertDialog
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.button.MaterialButton
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.nextcloud.client.di.Injectable
+import com.owncloud.android.R
+import com.owncloud.android.databinding.PasswordDialogBinding
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.lib.resources.shares.OCShare
+import com.owncloud.android.ui.activity.FileActivity
+import com.owncloud.android.utils.DisplayUtils
+import com.owncloud.android.utils.KeyboardUtils
+import com.owncloud.android.utils.theme.ViewThemeUtils
+import javax.inject.Inject
+
+/**
+ * Dialog to input the password for sharing a file/folder.
+ *
+ *
+ * Triggers the share when the password is introduced.
+ */
+class SharePasswordDialogFragment : DialogFragment(), Injectable {
+    @JvmField
+    @Inject
+    var viewThemeUtils: ViewThemeUtils? = null
+
+    @JvmField
+    @Inject
+    var keyboardUtils: KeyboardUtils? = null
+
+    private var binding: PasswordDialogBinding? = null
+    private var file: OCFile? = null
+    private var share: OCShare? = null
+    private var createShare = false
+    private var askForPassword = false
+
+    override fun onStart() {
+        super.onStart()
+
+        val alertDialog = dialog as AlertDialog?
+
+        if (alertDialog != null) {
+            val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton?
+            if (positiveButton != null) {
+                viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(positiveButton)
+                positiveButton.setOnClickListener {
+                    val sharePassword = binding?.sharePassword?.text
+
+                    if (sharePassword != null) {
+                        val password = sharePassword.toString()
+                        if (!askForPassword && TextUtils.isEmpty(password)) {
+                            DisplayUtils.showSnackMessage(binding?.root, R.string.share_link_empty_password)
+                            return@setOnClickListener
+                        }
+                        if (share == null) {
+                            setPassword(createShare, file, password)
+                        } else {
+                            setPassword(share!!, password)
+                        }
+                    }
+
+                    alertDialog.dismiss()
+                }
+            }
+
+            val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton?
+            if (negativeButton != null) {
+                viewThemeUtils?.material?.colorMaterialButtonPrimaryBorderless(negativeButton)
+            }
+
+            val neutralButton = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL) as MaterialButton?
+            if (neutralButton != null) {
+                val warningColorId = ContextCompat.getColor(requireContext(), R.color.highlight_textColor_Warning)
+                viewThemeUtils?.platform?.colorTextButtons(warningColorId, neutralButton)
+            }
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+        keyboardUtils?.showKeyboardForEditText(requireDialog().window, binding!!.sharePassword)
+    }
+
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        file = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            requireArguments().getParcelable(ARG_FILE, OCFile::class.java)
+        } else {
+            @Suppress("DEPRECATION")
+            requireArguments().getParcelable(ARG_FILE)
+        }
+
+        share = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            requireArguments().getParcelable(ARG_SHARE, OCShare::class.java)
+        } else {
+            @Suppress("DEPRECATION")
+            requireArguments().getParcelable(ARG_SHARE)
+        }
+
+        createShare = requireArguments().getBoolean(ARG_CREATE_SHARE, false)
+        askForPassword = requireArguments().getBoolean(ARG_ASK_FOR_PASSWORD, false)
+
+        // Inflate the layout for the dialog
+        val inflater = requireActivity().layoutInflater
+        binding = PasswordDialogBinding.inflate(inflater, null, false)
+
+        // Setup layout
+        binding?.sharePassword?.setText("")
+        viewThemeUtils?.material?.colorTextInputLayout(binding!!.sharePasswordContainer)
+
+        val neutralButtonTextId: Int
+        val title: Int
+        if (askForPassword) {
+            title = R.string.share_link_optional_password_title
+            neutralButtonTextId = R.string.common_skip
+        } else {
+            title = R.string.share_link_password_title
+            neutralButtonTextId = R.string.common_cancel
+        }
+
+        // Build the dialog
+        val builder = MaterialAlertDialogBuilder(requireContext())
+        builder.setView(binding!!.root)
+            .setPositiveButton(R.string.common_ok, null)
+            .setNegativeButton(R.string.common_delete) { _: DialogInterface?, _: Int -> callSetPassword() }
+            .setNeutralButton(neutralButtonTextId) { _: DialogInterface?, _: Int ->
+                if (askForPassword) {
+                    callSetPassword()
+                }
+            }
+            .setTitle(title)
+
+        viewThemeUtils?.dialog?.colorMaterialAlertDialogBackground(requireContext(), builder)
+
+        return builder.create()
+    }
+
+    private fun callSetPassword() {
+        if (share == null) {
+            setPassword(createShare, file, null)
+        } else {
+            setPassword(share!!, null)
+        }
+    }
+
+    private fun setPassword(createShare: Boolean, file: OCFile?, password: String?) {
+        val fileOperationsHelper = (requireActivity() as FileActivity).fileOperationsHelper ?: return
+        if (createShare) {
+            fileOperationsHelper.shareFileViaPublicShare(file, password)
+        } else {
+            fileOperationsHelper.setPasswordToShare(share, password)
+        }
+    }
+
+    private fun setPassword(share: OCShare, password: String?) {
+        val fileOperationsHelper = (requireActivity() as FileActivity).fileOperationsHelper ?: return
+        fileOperationsHelper.setPasswordToShare(share, password)
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        binding = null
+    }
+
+    companion object {
+        private const val ARG_FILE = "FILE"
+        private const val ARG_SHARE = "SHARE"
+        private const val ARG_CREATE_SHARE = "CREATE_SHARE"
+        private const val ARG_ASK_FOR_PASSWORD = "ASK_FOR_PASSWORD"
+        const val PASSWORD_FRAGMENT = "PASSWORD_FRAGMENT"
+
+        /**
+         * Public factory method to create new SharePasswordDialogFragment instances.
+         *
+         * @param file        OCFile bound to the public share that which
+         * password will be set or updated
+         * @param createShare When 'true', the request for password will be
+         * followed by the creation of a new public link
+         * when 'false', a public share is assumed to exist, and the password is bound to it.
+         * @return Dialog ready to show.
+         */
+        @JvmStatic
+        fun newInstance(file: OCFile?, createShare: Boolean, askForPassword: Boolean): SharePasswordDialogFragment {
+            val frag = SharePasswordDialogFragment()
+            val args = Bundle()
+            args.putParcelable(ARG_FILE, file)
+            args.putBoolean(ARG_CREATE_SHARE, createShare)
+            args.putBoolean(ARG_ASK_FOR_PASSWORD, askForPassword)
+            frag.arguments = args
+            return frag
+        }
+
+        /**
+         * Public factory method to create new SharePasswordDialogFragment instances.
+         *
+         * @param share OCFile bound to the public share that which password will be set or updated
+         * @return Dialog ready to show.
+         */
+        @JvmStatic
+        fun newInstance(share: OCShare?, askForPassword: Boolean): SharePasswordDialogFragment {
+            val frag = SharePasswordDialogFragment()
+            val args = Bundle()
+            args.putParcelable(ARG_SHARE, share)
+            args.putBoolean(ARG_ASK_FOR_PASSWORD, askForPassword)
+            frag.arguments = args
+            return frag
+        }
+
+        /**
+         * Public factory method to create new SharePasswordDialogFragment instances.
+         *
+         * @param share OCFile bound to the public share that which password will be set or updated
+         * @return Dialog ready to show.
+         */
+        fun newInstance(share: OCShare?): SharePasswordDialogFragment {
+            val frag = SharePasswordDialogFragment()
+            val args = Bundle()
+            args.putParcelable(ARG_SHARE, share)
+            frag.arguments = args
+            return frag
+        }
+    }
+}