mirror of
https://github.com/nextcloud/android.git
synced 2024-11-22 21:25:35 +03:00
Merge pull request #12047 from nextcloud/feature/use-m3-SharePasswordDialogFragment
Use Material Design 3 share password dialog fragment
This commit is contained in:
commit
c52bad82f0
4 changed files with 250 additions and 227 deletions
Binary file not shown.
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.3 KiB |
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue