Browse Source

Merge pull request #12063 from nextcloud/feature/use-m3-SendShareDialog-bottomsheet

Use Material Design 3 For Send Share Dialog Bottomsheet
Andy Scherzinger 1 year ago
parent
commit
1096d8fa62

BIN
app/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendShareDialogTest_showDialog.png


+ 0 - 286
app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.java

@@ -1,286 +0,0 @@
-package com.owncloud.android.ui.dialog;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
-import com.google.android.material.snackbar.Snackbar;
-import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.utils.IntentUtil;
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.status.OCCapability;
-import com.owncloud.android.ui.activity.FileActivity;
-import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.ui.adapter.SendButtonAdapter;
-import com.owncloud.android.ui.components.SendButtonData;
-import com.owncloud.android.ui.helpers.FileOperationsHelper;
-import com.owncloud.android.utils.MimeTypeUtil;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * @author Andy Scherzinger
- * Copyright (C) 2017 Tobias Kaminsky
- * Copyright (C) 2017 Nextcloud 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 Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-public class SendShareDialog extends BottomSheetDialogFragment implements Injectable {
-
-    private static final String KEY_OCFILE = "KEY_OCFILE";
-    private static final String KEY_SHARING_PUBLIC_PASSWORD_ENFORCED = "KEY_SHARING_PUBLIC_PASSWORD_ENFORCED";
-    private static final String KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD = "KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD";
-    private static final String KEY_HIDE_NCSHARING_OPTIONS = "KEY_HIDE_NCSHARING_OPTIONS";
-    private static final String TAG = SendShareDialog.class.getSimpleName();
-    public static final String PACKAGE_NAME = "PACKAGE_NAME";
-    public static final String ACTIVITY_NAME = "ACTIVITY_NAME";
-
-    private View view;
-    private OCFile file;
-    private boolean hideNcSharingOptions;
-    private boolean sharingPublicPasswordEnforced;
-    private boolean sharingPublicAskForPassword;
-    private FileOperationsHelper fileOperationsHelper;
-    @Inject ViewThemeUtils viewThemeUtils;
-
-    public static SendShareDialog newInstance(OCFile file, boolean hideNcSharingOptions, OCCapability capability) {
-
-        SendShareDialog dialogFragment = new SendShareDialog();
-
-        Bundle args = new Bundle();
-        args.putParcelable(KEY_OCFILE, file);
-        args.putBoolean(KEY_HIDE_NCSHARING_OPTIONS, hideNcSharingOptions);
-        args.putBoolean(KEY_SHARING_PUBLIC_PASSWORD_ENFORCED,
-                        capability.getFilesSharingPublicPasswordEnforced().isTrue());
-        args.putBoolean(KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD,
-                        capability.getFilesSharingPublicAskForOptionalPassword().isTrue());
-        dialogFragment.setArguments(args);
-
-        return dialogFragment;
-    }
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        // keep the state of the fragment on configuration changes
-        setRetainInstance(true);
-
-        file = getArguments().getParcelable(KEY_OCFILE);
-        hideNcSharingOptions = getArguments().getBoolean(KEY_HIDE_NCSHARING_OPTIONS, false);
-        sharingPublicPasswordEnforced = getArguments().getBoolean(KEY_SHARING_PUBLIC_PASSWORD_ENFORCED, false);
-        sharingPublicAskForPassword = getArguments().getBoolean(KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD);
-    }
-
-    @Nullable
-    @Override
-    public View onCreateView(@NonNull LayoutInflater inflater,
-                             @Nullable ViewGroup container,
-                             @Nullable Bundle savedInstanceState) {
-
-        view = inflater.inflate(R.layout.send_share_fragment, container, false);
-
-        LinearLayout sendShareButtons = view.findViewById(R.id.send_share_buttons);
-        View divider = view.findViewById(R.id.divider);
-
-        // Share with people
-        TextView sharePeopleText = view.findViewById(R.id.share_people_button);
-        sharePeopleText.setOnClickListener(v -> shareFile(file));
-
-        ImageView sharePeopleImageView = view.findViewById(R.id.share_people_icon);
-        themeShareButtonImage(sharePeopleImageView);
-        sharePeopleImageView.setOnClickListener(v -> shareFile(file));
-
-        // Share via link button
-        TextView shareLinkText = view.findViewById(R.id.share_link_button);
-        shareLinkText.setOnClickListener(v -> shareByLink());
-
-        ImageView shareLinkImageView = view.findViewById(R.id.share_link_icon);
-        themeShareButtonImage(shareLinkImageView);
-        shareLinkImageView.setOnClickListener(v -> shareByLink());
-
-        if (hideNcSharingOptions) {
-            sendShareButtons.setVisibility(View.GONE);
-            divider.setVisibility(View.GONE);
-        } else if (file.isSharedWithMe() && !file.canReshare()) {
-            showResharingNotAllowedSnackbar();
-
-            if (file.isFolder()) {
-                shareLinkText.setVisibility(View.GONE);
-                shareLinkImageView.setVisibility(View.GONE);
-                sharePeopleText.setVisibility(View.GONE);
-                sharePeopleImageView.setVisibility(View.GONE);
-                getDialog().hide();
-            } else {
-                shareLinkText.setEnabled(false);
-                shareLinkText.setAlpha(0.3f);
-                shareLinkImageView.setEnabled(false);
-                shareLinkImageView.setAlpha(0.3f);
-                sharePeopleText.setEnabled(false);
-                sharePeopleText.setAlpha(0.3f);
-                sharePeopleImageView.setEnabled(false);
-                sharePeopleImageView.setAlpha(0.3f);
-            }
-        }
-
-        // populate send apps
-        Intent sendIntent = IntentUtil.createSendIntent(requireContext(), file);
-
-        List<SendButtonData> sendButtonDataList = setupSendButtonData(sendIntent);
-
-        if ("off".equalsIgnoreCase(requireContext().getString(R.string.send_files_to_other_apps))) {
-            sharePeopleText.setVisibility(View.GONE);
-        }
-
-        SendButtonAdapter.ClickListener clickListener = setupSendButtonClickListener(sendIntent);
-
-        RecyclerView sendButtonsView = view.findViewById(R.id.send_button_recycler_view);
-        sendButtonsView.setLayoutManager(new GridLayoutManager(getActivity(), 4));
-        sendButtonsView.setAdapter(new SendButtonAdapter(sendButtonDataList, clickListener));
-
-        return view;
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        BottomSheetBehavior.from((View) requireView().getParent()).setState(BottomSheetBehavior.STATE_EXPANDED);
-    }
-
-    private void shareByLink() {
-        if (file.isSharedViaLink()) {
-            ((FileActivity) requireActivity()).getFileOperationsHelper().getFileWithLink(file, viewThemeUtils);
-        } else if (sharingPublicPasswordEnforced || sharingPublicAskForPassword) {
-            // password enforced by server, request to the user before trying to create
-            requestPasswordForShareViaLink();
-        } else {
-            // create without password if not enforced by server or we don't know if enforced;
-            ((FileActivity) requireActivity()).getFileOperationsHelper().shareFileViaPublicShare(file, null);
-        }
-
-        this.dismiss();
-    }
-
-    private void requestPasswordForShareViaLink() {
-        SharePasswordDialogFragment dialog = SharePasswordDialogFragment.newInstance(file,
-                                                                                     true,
-                                                                                     sharingPublicAskForPassword);
-        dialog.show(getFragmentManager(), SharePasswordDialogFragment.PASSWORD_FRAGMENT);
-    }
-
-    private void themeShareButtonImage(ImageView shareImageView) {
-        viewThemeUtils.files.themeAvatarButton(shareImageView);
-    }
-
-    private void showResharingNotAllowedSnackbar() {
-        Snackbar snackbar = Snackbar.make(view, R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG);
-        snackbar.addCallback(new Snackbar.Callback() {
-            @Override
-            public void onDismissed(Snackbar transientBottomBar, int event) {
-                super.onDismissed(transientBottomBar, event);
-
-                if (file.isFolder()) {
-                    dismiss();
-                }
-            }
-        });
-
-        snackbar.show();
-    }
-
-    @NonNull
-    private SendButtonAdapter.ClickListener setupSendButtonClickListener(Intent sendIntent) {
-        return sendButtonDataData -> {
-            String packageName = sendButtonDataData.getPackageName();
-            String activityName = sendButtonDataData.getActivityName();
-
-            if (MimeTypeUtil.isImage(file) && !file.isDown()) {
-                fileOperationsHelper.sendCachedImage(file, packageName, activityName);
-            } else {
-                // Obtain the file
-                if (file.isDown()) {
-                    sendIntent.setComponent(new ComponentName(packageName, activityName));
-                    requireActivity().startActivity(Intent.createChooser(sendIntent, getString(R.string.send)));
-                } else {  // Download the file
-                    Log_OC.d(TAG, file.getRemotePath() + ": File must be downloaded");
-                    ((SendShareDialog.SendShareDialogDownloader) requireActivity())
-                        .downloadFile(file, packageName, activityName);
-                }
-            }
-
-            dismiss();
-        };
-    }
-
-    @NonNull
-    private List<SendButtonData> setupSendButtonData(Intent sendIntent) {
-        Drawable icon;
-        SendButtonData sendButtonData;
-        CharSequence label;
-        List<ResolveInfo> matches = requireActivity().getPackageManager().queryIntentActivities(sendIntent, 0);
-        List<SendButtonData> sendButtonDataList = new ArrayList<>(matches.size());
-        for (ResolveInfo match : matches) {
-            icon = match.loadIcon(requireActivity().getPackageManager());
-            label = match.loadLabel(requireActivity().getPackageManager());
-            sendButtonData = new SendButtonData(icon, label,
-                    match.activityInfo.packageName,
-                    match.activityInfo.name);
-
-            sendButtonDataList.add(sendButtonData);
-        }
-        return sendButtonDataList;
-    }
-
-    private void shareFile(OCFile file) {
-        dismiss();
-
-        if (getActivity() instanceof FileDisplayActivity) {
-            ((FileDisplayActivity) getActivity()).showDetails(file, 1);
-        } else {
-            fileOperationsHelper.showShareFile(file);
-        }
-    }
-
-    public void setFileOperationsHelper(FileOperationsHelper fileOperationsHelper) {
-        this.fileOperationsHelper = fileOperationsHelper;
-    }
-
-    public interface SendShareDialogDownloader {
-        void downloadFile(OCFile file, String packageName, String activityName);
-    }
-}

+ 274 - 0
app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.kt

@@ -0,0 +1,274 @@
+package com.owncloud.android.ui.dialog
+
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.drawable.Drawable
+import android.os.Build
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.GridLayoutManager
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.android.common.ui.theme.utils.ColorRole
+import com.nextcloud.client.di.Injectable
+import com.nextcloud.client.utils.IntentUtil.createSendIntent
+import com.owncloud.android.R
+import com.owncloud.android.databinding.SendShareFragmentBinding
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.lib.common.utils.Log_OC
+import com.owncloud.android.lib.resources.status.OCCapability
+import com.owncloud.android.ui.activity.FileActivity
+import com.owncloud.android.ui.activity.FileDisplayActivity
+import com.owncloud.android.ui.adapter.SendButtonAdapter
+import com.owncloud.android.ui.components.SendButtonData
+import com.owncloud.android.ui.helpers.FileOperationsHelper
+import com.owncloud.android.utils.MimeTypeUtil
+import com.owncloud.android.utils.theme.ViewThemeUtils
+import javax.inject.Inject
+
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * @author Andy Scherzinger
+ * Copyright (C) 2017 Tobias Kaminsky
+ * Copyright (C) 2017 Nextcloud 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 Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+class SendShareDialog : BottomSheetDialogFragment(R.layout.send_share_fragment), Injectable {
+
+    private lateinit var binding: SendShareFragmentBinding
+
+    private var file: OCFile? = null
+    private var hideNcSharingOptions = false
+    private var sharingPublicPasswordEnforced = false
+    private var sharingPublicAskForPassword = false
+    private var fileOperationsHelper: FileOperationsHelper? = null
+
+    @JvmField
+    @Inject
+    var viewThemeUtils: ViewThemeUtils? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        // keep the state of the fragment on configuration changes
+        retainInstance = true
+        val arguments = requireArguments()
+
+        file = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            arguments.getParcelable(KEY_OCFILE, OCFile::class.java)
+        } else {
+            @Suppress("DEPRECATION")
+            arguments.getParcelable(KEY_OCFILE)
+        }
+
+        hideNcSharingOptions = arguments.getBoolean(KEY_HIDE_NCSHARING_OPTIONS, false)
+        sharingPublicPasswordEnforced = arguments.getBoolean(KEY_SHARING_PUBLIC_PASSWORD_ENFORCED, false)
+        sharingPublicAskForPassword = arguments.getBoolean(KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+        binding = SendShareFragmentBinding.inflate(inflater, container, false)
+
+        binding.btnShare.setOnClickListener { shareFile(file) }
+        binding.btnLink.setOnClickListener { shareByLink() }
+
+        applyTintColor()
+        setupBottomSheetBehaviour()
+        checkButtonVisibilities()
+        setupSendButtonRecyclerView()
+
+        return binding.root
+    }
+
+    @Suppress("MagicNumber")
+    private fun setupSendButtonRecyclerView() {
+        val sendIntent = createSendIntent(requireContext(), file!!)
+        val sendButtonDataList = setupSendButtonData(sendIntent)
+        val clickListener = setupSendButtonClickListener(sendIntent)
+
+        binding.sendButtonRecyclerView.layoutManager = GridLayoutManager(activity, 4)
+        binding.sendButtonRecyclerView.adapter = SendButtonAdapter(sendButtonDataList, clickListener)
+    }
+
+    private fun setupBottomSheetBehaviour() {
+        val bottomSheetDialog = dialog as BottomSheetDialog
+        bottomSheetDialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
+        bottomSheetDialog.behavior.skipCollapsed = true
+    }
+
+    private fun applyTintColor() {
+        viewThemeUtils?.material?.colorMaterialButtonPrimaryFilled(binding.btnLink)
+        viewThemeUtils?.material?.colorMaterialButtonPrimaryFilled(binding.btnShare)
+        viewThemeUtils?.platform?.colorViewBackground(binding.bottomSheet, ColorRole.SURFACE)
+    }
+
+    @Suppress("MagicNumber")
+    private fun checkButtonVisibilities() {
+        if (hideNcSharingOptions) {
+            binding.sendShareButtons.visibility = View.GONE
+            binding.divider.visibility = View.GONE
+        } else if (file?.isSharedWithMe == true && file?.canReshare() == false) {
+            showSharingNotAllowedMessage()
+
+            if (file?.isFolder == true) {
+                binding.btnShare.visibility = View.GONE
+                binding.btnLink.visibility = View.GONE
+                dialog!!.hide()
+            } else {
+                binding.btnLink.isEnabled = false
+                binding.btnLink.alpha = 0.3f
+
+                binding.btnShare.isEnabled = false
+                binding.btnShare.alpha = 0.3f
+            }
+        }
+    }
+
+    private fun shareByLink() {
+        val fileOperationsHelper = (requireActivity() as FileActivity).fileOperationsHelper
+
+        if (file?.isSharedViaLink == true) {
+            fileOperationsHelper.getFileWithLink(file!!, viewThemeUtils)
+        } else if (sharingPublicPasswordEnforced || sharingPublicAskForPassword) {
+            // password enforced by server, request to the user before trying to create
+            requestPasswordForShareViaLink()
+        } else {
+            // create without password if not enforced by server or we don't know if enforced;
+            fileOperationsHelper.shareFileViaPublicShare(file, null)
+        }
+
+        dismiss()
+    }
+
+    private fun requestPasswordForShareViaLink() {
+        val dialog = SharePasswordDialogFragment.newInstance(
+            file,
+            true,
+            sharingPublicAskForPassword
+        )
+
+        dialog.show(parentFragmentManager, SharePasswordDialogFragment.PASSWORD_FRAGMENT)
+    }
+
+    private fun showSharingNotAllowedMessage() {
+        val message = Snackbar.make(binding.root, R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG)
+
+        message.addCallback(object : Snackbar.Callback() {
+            override fun onDismissed(transientBottomBar: Snackbar, event: Int) {
+                super.onDismissed(transientBottomBar, event)
+                if (file!!.isFolder) {
+                    dismiss()
+                }
+            }
+        })
+
+        message.show()
+    }
+
+    private fun setupSendButtonClickListener(sendIntent: Intent): SendButtonAdapter.ClickListener {
+        return SendButtonAdapter.ClickListener { sendButtonDataData: SendButtonData ->
+            val packageName = sendButtonDataData.packageName
+            val activityName = sendButtonDataData.activityName
+
+            if (MimeTypeUtil.isImage(file) && !file!!.isDown) {
+                fileOperationsHelper?.sendCachedImage(file, packageName, activityName)
+            } else {
+                // Obtain the file
+                if (file!!.isDown) {
+                    sendIntent.component = ComponentName(packageName, activityName)
+                    requireActivity().startActivity(Intent.createChooser(sendIntent, getString(R.string.send)))
+                } else { // Download the file
+                    Log_OC.d(TAG, file!!.remotePath + ": File must be downloaded")
+                    (requireActivity() as SendShareDialogDownloader)
+                        .downloadFile(file, packageName, activityName)
+                }
+            }
+
+            dismiss()
+        }
+    }
+
+    private fun setupSendButtonData(sendIntent: Intent): List<SendButtonData> {
+        var icon: Drawable
+        var sendButtonData: SendButtonData
+        var label: CharSequence
+        val matches = requireActivity().packageManager.queryIntentActivities(sendIntent, 0)
+        val sendButtonDataList: MutableList<SendButtonData> = ArrayList(matches.size)
+        for (match in matches) {
+            icon = match.loadIcon(requireActivity().packageManager)
+            label = match.loadLabel(requireActivity().packageManager)
+            sendButtonData = SendButtonData(
+                icon, label,
+                match.activityInfo.packageName,
+                match.activityInfo.name
+            )
+            sendButtonDataList.add(sendButtonData)
+        }
+        return sendButtonDataList
+    }
+
+    private fun shareFile(file: OCFile?) {
+        dismiss()
+
+        if (activity is FileDisplayActivity) {
+            (activity as FileDisplayActivity?)?.showDetails(file, 1)
+        } else {
+            fileOperationsHelper?.showShareFile(file)
+        }
+    }
+
+    fun setFileOperationsHelper(fileOperationsHelper: FileOperationsHelper?) {
+        this.fileOperationsHelper = fileOperationsHelper
+    }
+
+    interface SendShareDialogDownloader {
+        fun downloadFile(file: OCFile?, packageName: String?, activityName: String?)
+    }
+
+    companion object {
+        private const val KEY_OCFILE = "KEY_OCFILE"
+        private const val KEY_SHARING_PUBLIC_PASSWORD_ENFORCED = "KEY_SHARING_PUBLIC_PASSWORD_ENFORCED"
+        private const val KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD = "KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD"
+        private const val KEY_HIDE_NCSHARING_OPTIONS = "KEY_HIDE_NCSHARING_OPTIONS"
+        private val TAG = SendShareDialog::class.java.simpleName
+        const val PACKAGE_NAME = "PACKAGE_NAME"
+        const val ACTIVITY_NAME = "ACTIVITY_NAME"
+
+        @JvmStatic
+        fun newInstance(file: OCFile?, hideNcSharingOptions: Boolean, capability: OCCapability): SendShareDialog {
+            val dialogFragment = SendShareDialog()
+            val args = Bundle()
+            args.putParcelable(KEY_OCFILE, file)
+            args.putBoolean(KEY_HIDE_NCSHARING_OPTIONS, hideNcSharingOptions)
+            args.putBoolean(
+                KEY_SHARING_PUBLIC_PASSWORD_ENFORCED,
+                capability.filesSharingPublicPasswordEnforced.isTrue
+            )
+            args.putBoolean(
+                KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD,
+                capability.filesSharingPublicAskForOptionalPassword.isTrue
+            )
+            dialogFragment.arguments = args
+            return dialogFragment
+        }
+    }
+}

+ 43 - 77
app/src/main/res/layout/send_share_fragment.xml

@@ -19,102 +19,68 @@
  You should have received a copy of the GNU Affero General Public License
  along with this program. If not, see <http://www.gnu.org/licenses/>.
 -->
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/standard_bottom_sheet"
+    style="@style/Widget.Material3.BottomSheet"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@color/bg_default">
+    android:layout_height="wrap_content"
+    android:layout_gravity="bottom"
+    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
 
-    <RelativeLayout
+    <LinearLayout
+        android:id="@+id/bottom_sheet"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <com.google.android.material.bottomsheet.BottomSheetDragHandleView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
 
         <LinearLayout
             android:id="@+id/send_share_buttons"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginEnd="@dimen/send_share_fragment_layout_margin"
-            android:layout_marginLeft="@dimen/send_share_fragment_layout_margin"
-            android:layout_marginRight="@dimen/send_share_fragment_layout_margin"
-            android:layout_marginStart="@dimen/send_share_fragment_layout_margin"
+            android:gravity="center"
             android:orientation="horizontal"
-            android:baselineAligned="false"
-            android:padding="@dimen/send_share_fragment_layout_padding">
-
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            tools:ignore="UseCompoundDrawables">
+            android:paddingBottom="@dimen/standard_margin">
 
-            <ImageView
-                android:id="@+id/share_people_icon"
-                android:layout_width="@dimen/share_icon_size"
-                android:layout_height="@dimen/share_icon_size"
-                android:layout_gravity="center_horizontal"
-                android:contentDescription="@string/share"
-                android:src="@drawable/shared_via_users"
-                android:paddingTop="@dimen/share_people_icon_layout_padding"
-                android:paddingEnd="@dimen/share_people_icon_layout_padding"
-                android:paddingBottom="@dimen/share_people_icon_layout_padding"
-                android:paddingStart="@dimen/standard_half_padding"
-                android:background="@drawable/round_bgnd"/>
-
-            <TextView
-                android:id="@+id/share_people_button"
+            <com.google.android.material.button.MaterialButton
+                android:id="@+id/btn_share"
+                style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:drawable="@drawable/ic_share"
                 android:text="@string/share"
-                android:paddingTop="@dimen/standard_half_padding"
-                android:textColor="@color/text_color"/>
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            tools:ignore="UseCompoundDrawables">
-
-            <ImageView
-                android:id="@+id/share_link_icon"
-                android:layout_width="@dimen/share_icon_size"
-                android:layout_height="@dimen/share_icon_size"
-                android:layout_gravity="center_horizontal"
-                android:contentDescription="@string/link"
-                android:src="@drawable/shared_via_link"
-                android:padding="12dp"
-                android:background="@drawable/round_bgnd"/>
+                app:iconPadding="@dimen/standard_half_padding"
+                app:icon="@drawable/shared_via_users" />
 
-            <TextView
-                android:id="@+id/share_link_button"
+            <com.google.android.material.button.MaterialButton
+                android:id="@+id/btn_link"
+                style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:drawable="@drawable/ic_share"
+                app:iconPadding="@dimen/standard_half_padding"
                 android:text="@string/link"
-                android:paddingTop="@dimen/standard_half_padding"
-                android:textColor="@color/text_color"/>
-        </LinearLayout>
+                app:icon="@drawable/shared_via_link" />
 
-    </LinearLayout>
+        </LinearLayout>
 
-    <View
-        android:id="@+id/divider"
-        android:layout_width="match_parent"
-        android:layout_height="1dp"
-        android:layout_below="@id/send_share_buttons"
-        android:alpha="0.3"
-        android:background="@color/background_color_inverse"/>
+        <View
+            android:id="@+id/divider"
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:alpha="0.3"
+            android:background="@color/background_color_inverse"/>
 
         <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/send_button_recycler_view"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/divider"
-        tools:listitem="@layout/send_button" />
-    </RelativeLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
+            android:id="@+id/send_button_recycler_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            tools:listitem="@layout/send_button" />
+
+    </LinearLayout>
+
+</FrameLayout>

+ 0 - 3
app/src/main/res/values/dims.xml

@@ -121,9 +121,6 @@
     <dimen name="preview_error_image_layout_width">72dp</dimen>
     <dimen name="preview_error_image_layout_height">72dp</dimen>
     <dimen name="preview_error_text_size">26sp</dimen>
-    <dimen name="send_share_fragment_layout_margin">24dp</dimen>
-    <dimen name="send_share_fragment_layout_padding">24dp</dimen>
-    <dimen name="share_people_icon_layout_padding">12dp</dimen>
     <dimen name="synced_folders_item_type_layout_width">32dp</dimen>
     <dimen name="synced_folders_item_type_layout_height">32dp</dimen>
     <dimen name="synced_folders_item_type_layout_right_end_margin">24dp</dimen>

+ 1 - 1
scripts/analysis/lint-results.txt

@@ -1,2 +1,2 @@
 DO NOT TOUCH; GENERATED BY DRONE
-      <span class="mdl-layout-title">Lint Report: 79 warnings</span>
+      <span class="mdl-layout-title">Lint Report: 78 warnings</span>