Browse Source

FileActionsBottomSheet: fix things that were parameters, but shouldn't

- Result listener should be done through the fragmentResultListener API
- ComponentsGetter is attached on onAttach

This avoids crashes on config changes, etc

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey 2 years ago
parent
commit
702a9cedf0

+ 37 - 16
app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt

@@ -22,6 +22,7 @@
 
 package com.nextcloud.ui.fileactions
 
+import android.content.Context
 import android.content.res.ColorStateList
 import android.graphics.Typeface
 import android.graphics.drawable.Drawable
@@ -31,8 +32,12 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import androidx.annotation.IdRes
+import androidx.appcompat.content.res.AppCompatResources
 import androidx.core.os.bundleOf
 import androidx.core.view.isVisible
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.setFragmentResult
+import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.ViewModelProvider
 import com.google.android.material.bottomsheet.BottomSheetDialogFragment
 import com.nextcloud.client.account.CurrentAccountProvider
@@ -51,11 +56,6 @@ import javax.inject.Inject
 
 class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment(), Injectable {
 
-    lateinit var componentsGetter: ComponentsGetter
-
-    // TODO replace with fragment listener from Activity
-    lateinit var clickListener: ClickListener
-
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
@@ -71,6 +71,8 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
     private val binding
         get() = _binding!!
 
+    lateinit var componentsGetter: ComponentsGetter
+
     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
         val args = requireArguments()
         // todo parse bundle in viewmodel, not here
@@ -110,6 +112,14 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         return binding.root
     }
 
+    override fun onAttach(context: Context) {
+        super.onAttach(context)
+        require(context is ComponentsGetter) {
+            "Context is not a ComponentsGetter"
+        }
+        this.componentsGetter = context
+    }
+
     private fun toggleLoadingOrContent(state: FileActionsViewModel.UiState) {
         if (state is FileActionsViewModel.UiState.Loading) {
             binding.bottomSheetLoading.isVisible = true
@@ -203,7 +213,7 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
                     val drawable =
                         viewThemeUtils.platform.tintDrawable(
                             requireContext(),
-                            resources.getDrawable(action.icon)
+                            AppCompatResources.getDrawable(requireContext(), action.icon)!!
                         )
                     icon.setImageDrawable(drawable)
                 }
@@ -213,7 +223,8 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
 
     private fun dispatchActionClick(id: Int?) {
         if (id != null) {
-            clickListener.onClick(id)
+            setFragmentResult(REQUEST_KEY, bundleOf(RESULT_KEY_ACTION_ID to id))
+            parentFragmentManager.clearFragmentResultListener(REQUEST_KEY)
             dismiss()
         }
     }
@@ -223,11 +234,27 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         _binding = null
     }
 
-    interface ClickListener {
-        fun onClick(@IdRes itemId: Int)
+    interface ResultListener {
+        fun onResult(@IdRes actionId: Int)
+    }
+
+    fun setResultListener(
+        fragmentManager: FragmentManager,
+        lifecycleOwner: LifecycleOwner,
+        listener: ResultListener
+    ): FileActionsBottomSheet {
+        fragmentManager.setFragmentResultListener(REQUEST_KEY, lifecycleOwner) { _, result ->
+            @IdRes val actionId = result.getInt(RESULT_KEY_ACTION_ID, -1)
+            if (actionId != -1) {
+                listener.onResult(actionId)
+            }
+        }
+        return this
     }
 
     companion object {
+        private const val REQUEST_KEY = "REQUEST_KEY_ACTION"
+        private const val RESULT_KEY_ACTION_ID = "RESULT_KEY_ACTION_ID"
         private const val ARG_ALL_FILES_COUNT = "ALL_FILES_COUNT"
         private const val ARG_FILES = "FILES"
         private const val ARG_IS_OVERFLOW = "OVERFLOW"
@@ -237,13 +264,11 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         @JvmOverloads
         fun newInstance(
             file: OCFile,
-            componentsGetter: ComponentsGetter,
             isOverflow: Boolean,
-            onItemClick: ClickListener,
             @IdRes
             additionalToHide: List<Int>? = null
         ): FileActionsBottomSheet {
-            return newInstance(1, listOf(file), componentsGetter, isOverflow, onItemClick, additionalToHide)
+            return newInstance(1, listOf(file), isOverflow, additionalToHide)
         }
 
         @JvmStatic
@@ -251,9 +276,7 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         fun newInstance(
             numberOfAllFiles: Int,
             files: Collection<OCFile>,
-            componentsGetter: ComponentsGetter,
             isOverflow: Boolean,
-            onItemClick: ClickListener,
             @IdRes
             additionalToHide: List<Int>? = null
         ): FileActionsBottomSheet {
@@ -267,8 +290,6 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
                     argsBundle.putIntArray(ARG_ADDITIONAL_FILTER, additionalToHide.toIntArray())
                 }
                 arguments = argsBundle
-                this.componentsGetter = componentsGetter
-                this.clickListener = onItemClick
             }
         }
     }

+ 7 - 3
app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -84,9 +84,11 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.core.content.res.ResourcesCompat;
+import androidx.fragment.app.FragmentManager;
 
 /**
  * This Fragment is used to display the details about a file.
@@ -260,8 +262,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             additionalFilter.add(R.id.action_send_file);
             additionalFilter.add(R.id.action_sync_file);
         }
-        FileActionsBottomSheet.newInstance(file, containerActivity, true, this::optionsItemSelected, additionalFilter)
-            .show(getActivity().getSupportFragmentManager(), "actions");
+        final FragmentManager fragmentManager = getChildFragmentManager();
+        FileActionsBottomSheet.newInstance(file, true, additionalFilter)
+            .setResultListener(fragmentManager, this, this::optionsItemSelected)
+            .show(fragmentManager, "actions");
     }
 
     private void setupViewPager() {
@@ -383,7 +387,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         MenuUtils.hideAll(menu);
     }
 
-    private void optionsItemSelected(final int itemId) {
+    private void optionsItemSelected(@IdRes final int itemId) {
         if (itemId == R.id.action_send_file) {
             containerActivity.getFileOperationsHelper().sendShareFile(getFile(), true);
         } else if (itemId == R.id.action_open_file_with) {

+ 14 - 29
app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -132,6 +132,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
 import androidx.core.content.ContextCompat;
 import androidx.drawerlayout.widget.DrawerLayout;
 import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
@@ -571,30 +572,20 @@ public class OCFileListFragment extends ExtendedListFragment implements
 
     @Override
     public void onOverflowIconClicked(OCFile file, View view) {
+        final Set<OCFile> checkedFiles = new HashSet<>();
+        checkedFiles.add(file);
+        openActionsMenu(1, checkedFiles, true);
+    }
+
+    public void openActionsMenu(final int filesCount, final Set<OCFile> checkedFiles, final boolean isOverflow) {
         throttler.run("overflowClick", () -> {
-            FileActionsBottomSheet.newInstance(file, mContainerActivity, true, itemId -> {
-                    Set<OCFile> checkedFiles = new HashSet<>();
-                    checkedFiles.add(file);
-                    onFileActionChosen(itemId, checkedFiles);
+            final FragmentManager childFragmentManager = getChildFragmentManager();
+            FileActionsBottomSheet.newInstance(filesCount, checkedFiles, isOverflow)
+                .setResultListener(childFragmentManager, this, (id) -> {
+                    onFileActionChosen(id, checkedFiles);
                 })
-                .show(getActivity().getSupportFragmentManager(), "actions");
-
-//            final ThemedPopupMenu popup = new ThemedPopupMenu(requireContext(), view);
-//            popup.inflate(R.menu.item_file);
-//            FileMenuFilter mf = new FileMenuFilter(mAdapter.getFiles().size(),
-//                                                   Collections.singleton(file),
-//                                                   mContainerActivity, getActivity(),
-//                                                   true,
-//                                                   accountManager.getUser());
-//            mf.filter(popup.getMenu(), true);
-//            new FileLockingMenuCustomization(requireContext()).customizeMenu(popup.getMenu(), file);
-//            popup.setOnMenuItemClickListener(item -> {
-//                Set<OCFile> checkedFiles = new HashSet<>();
-//                checkedFiles.add(file);
-//                return onFileActionChosen(item, checkedFiles);
-//            });
-//
-////            popup.show();
+                .show(childFragmentManager, "actions");
+            ;
         });
     }
 
@@ -761,12 +752,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
             final Set<OCFile> checkedFiles = getCommonAdapter().getCheckedItems();
             if (item.getItemId() == R.id.custom_menu_placeholder_item) {
-                FileActionsBottomSheet.newInstance(getCommonAdapter().getFilesCount(),
-                                                   checkedFiles,
-                                                   mContainerActivity,
-                                                   false,
-                                                   itemId -> onFileActionChosen(itemId, checkedFiles))
-                    .show(getActivity().getSupportFragmentManager(), "actions");
+                openActionsMenu(getCommonAdapter().getFilesCount(), checkedFiles, false);
             }
             return true;
         }
@@ -1103,7 +1089,6 @@ public class OCFileListFragment extends ExtendedListFragment implements
     /**
      * Start the appropriate action(s) on the currently selected files given menu selected by the user.
      *
-     * @param item         MenuItem selected by the user
      * @param checkedFiles List of files selected by the user on which the action should be performed
      * @return 'true' if the menu selection started any action, 'false' otherwise.
      */

+ 5 - 7
app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -54,7 +54,6 @@ import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
-import com.nextcloud.utils.MenuUtils;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.databinding.PreviewImageFragmentBinding;
@@ -83,6 +82,7 @@ import javax.inject.Inject;
 import androidx.annotation.NonNull;
 import androidx.annotation.StringRes;
 import androidx.core.content.res.ResourcesCompat;
+import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentStatePagerAdapter;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import pl.droidsonroids.gif.GifDrawable;
@@ -370,12 +370,10 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
                     if (getFile() != null && getFile().isSharedWithMe() && !getFile().canReshare()) {
                         additionalFilter.add(R.id.action_send_share_file);
                     }
-                    FileActionsBottomSheet.newInstance(fileNew,
-                                                       containerActivity,
-                                                       false,
-                                                       this::onFileActionChosen,
-                                                       additionalFilter)
-                        .show(getActivity().getSupportFragmentManager(), "actions");
+                    final FragmentManager fragmentManager = getChildFragmentManager();
+                    FileActionsBottomSheet.newInstance(file, false, additionalFilter)
+                        .setResultListener(fragmentManager, this, this::onFileActionChosen)
+                        .show(fragmentManager, "actions");
                 }
             }
             return true;

+ 5 - 6
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -86,6 +86,7 @@ import androidx.annotation.NonNull;
 import androidx.annotation.StringRes;
 import androidx.appcompat.widget.AppCompatImageButton;
 import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.fragment.app.FragmentManager;
 
 /**
  * This fragment shows a preview of a downloaded media file (audio or video).
@@ -398,12 +399,10 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
                     if (getFile() != null && getFile().isSharedWithMe() && !getFile().canReshare()) {
                         additionalFilter.add(R.id.action_send_share_file);
                     }
-                    FileActionsBottomSheet.newInstance(fileNew,
-                                                       containerActivity,
-                                                       false,
-                                                       this::onFileActionChosen,
-                                                       additionalFilter)
-                        .show(getActivity().getSupportFragmentManager(), "actions");
+                    final FragmentManager fragmentManager = getChildFragmentManager();
+                    FileActionsBottomSheet.newInstance(file, false, additionalFilter)
+                        .setResultListener(fragmentManager, this, this::onFileActionChosen)
+                        .show(fragmentManager, "actions");
                 }
             }
             return true;

+ 5 - 7
app/src/main/java/com/owncloud/android/ui/preview/PreviewTextFileFragment.java

@@ -35,7 +35,6 @@ import android.widget.TextView;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
-import com.nextcloud.utils.MenuUtils;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -64,6 +63,7 @@ import javax.inject.Inject;
 import androidx.annotation.NonNull;
 import androidx.appcompat.widget.SearchView;
 import androidx.core.view.MenuItemCompat;
+import androidx.fragment.app.FragmentManager;
 
 public class PreviewTextFileFragment extends PreviewTextFragment {
     private static final String EXTRA_FILE = "FILE";
@@ -299,12 +299,10 @@ public class PreviewTextFileFragment extends PreviewTextFragment {
                     if (getFile() != null && getFile().isSharedWithMe() && !getFile().canReshare()) {
                         additionalFilter.add(R.id.action_send_share_file);
                     }
-                    FileActionsBottomSheet.newInstance(fileNew,
-                                                       containerActivity,
-                                                       false,
-                                                       this::onFileActionChosen,
-                                                       additionalFilter)
-                        .show(getActivity().getSupportFragmentManager(), "actions");
+                    final FragmentManager fragmentManager = getChildFragmentManager();
+                    FileActionsBottomSheet.newInstance(file, false, additionalFilter)
+                        .setResultListener(fragmentManager, this, this::onFileActionChosen)
+                        .show(fragmentManager, "actions");
                 }
             }
             return true;