From d1ebe33f465aacb792c2c78f658ce7a4c9b74b8d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 11 Mar 2026 16:46:26 +0100 Subject: [PATCH 1/3] refactor: send button Signed-off-by: alperozturk96 --- .../android/ui/adapter/SendButtonAdapter.java | 79 --------------- .../adapter/sendButton/SendButtonAdapter.kt | 60 ++++++++++++ .../ui/adapter/sendButton/SendButtonData.kt | 17 ++++ .../android/ui/components/SendButtonData.java | 40 -------- .../android/ui/dialog/SendFilesDialog.kt | 52 +++++----- .../android/ui/dialog/SendShareDialog.kt | 97 ++++++++++--------- app/src/main/res/layout/send_button.xml | 53 ++++------ 7 files changed, 175 insertions(+), 223 deletions(-) delete mode 100644 app/src/main/java/com/owncloud/android/ui/adapter/SendButtonAdapter.java create mode 100644 app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonAdapter.kt create mode 100644 app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonData.kt delete mode 100644 app/src/main/java/com/owncloud/android/ui/components/SendButtonData.java diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/SendButtonAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/SendButtonAdapter.java deleted file mode 100644 index 7965238316a7..000000000000 --- a/app/src/main/java/com/owncloud/android/ui/adapter/SendButtonAdapter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2017 Tobias Kaminsky - * SPDX-FileCopyrightText: 2017 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.owncloud.android.ui.adapter; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.owncloud.android.databinding.SendButtonBinding; -import com.owncloud.android.ui.components.SendButtonData; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -public class SendButtonAdapter extends RecyclerView.Adapter { - - private List sendButtonDataList; - private ClickListener clickListener; - - public SendButtonAdapter(List sendButtonDataList, ClickListener clickListener) { - this.sendButtonDataList = sendButtonDataList; - this.clickListener = clickListener; - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ViewHolder(SendButtonBinding.inflate(LayoutInflater.from(parent.getContext()), parent, - false), clickListener); - } - - @Override - public void onBindViewHolder(ViewHolder holder, int position) { - holder.bind(sendButtonDataList.get(position)); - } - - @Override - public int getItemCount() { - return sendButtonDataList.size(); - } - - public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - - private SendButtonBinding binding; - private ClickListener clickListener; - private SendButtonData sendButtonDataData; - - public ViewHolder(@NonNull SendButtonBinding binding, ClickListener clickListener) { - super(binding.getRoot()); - this.binding = binding; - this.clickListener = clickListener; - itemView.setOnClickListener(this); - } - - public void bind(SendButtonData item) { - sendButtonDataData = item; - binding.sendButtonIcon.setImageDrawable(item.getDrawable()); - binding.sendButtonText.setText(item.getTitle()); - } - - @Override - public void onClick(View v) { - if (clickListener != null) { - clickListener.onClick(sendButtonDataData); - } - } - } - - public interface ClickListener { - void onClick(SendButtonData sendButtonDataData); - } -} diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonAdapter.kt b/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonAdapter.kt new file mode 100644 index 000000000000..05b66cd5ad8a --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonAdapter.kt @@ -0,0 +1,60 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.adapter.sendButton + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.owncloud.android.databinding.SendButtonBinding + +class SendButtonAdapter( + private val sendButtonDataList: List, + private val clickListener: ClickListener +) : RecyclerView.Adapter() { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder( + SendButtonBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ), + clickListener + ) + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(sendButtonDataList[position]) + } + + override fun getItemCount(): Int = sendButtonDataList.size + + class ViewHolder(private val binding: SendButtonBinding, private val clickListener: ClickListener) : + RecyclerView.ViewHolder( + binding.getRoot() + ), + View.OnClickListener { + private var sendButtonDataData: SendButtonData? = null + + init { + itemView.setOnClickListener(this) + } + + fun bind(item: SendButtonData) { + sendButtonDataData = item + binding.sendButton.icon = item.drawable + binding.sendButton.text = item.title + } + + override fun onClick(v: View) { + clickListener.onSendButtonClick(sendButtonDataData) + } + } + + interface ClickListener { + fun onSendButtonClick(sendButtonData: SendButtonData?) + } +} diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonData.kt b/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonData.kt new file mode 100644 index 000000000000..1e618aaf2536 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/adapter/sendButton/SendButtonData.kt @@ -0,0 +1,17 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.adapter.sendButton + +import android.graphics.drawable.Drawable + +data class SendButtonData( + @JvmField val drawable: Drawable?, + @JvmField val title: CharSequence?, + val packageName: String?, + val activityName: String? +) diff --git a/app/src/main/java/com/owncloud/android/ui/components/SendButtonData.java b/app/src/main/java/com/owncloud/android/ui/components/SendButtonData.java deleted file mode 100644 index 558e27b02559..000000000000 --- a/app/src/main/java/com/owncloud/android/ui/components/SendButtonData.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2017 Tobias Kaminsky - * SPDX-FileCopyrightText: 2017 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.owncloud.android.ui.components; - -import android.graphics.drawable.Drawable; - -public class SendButtonData { - private Drawable drawable; - private CharSequence title; - private String packageName; - private String activityName; - - public SendButtonData(Drawable drawable, CharSequence title, String packageName, String activityName) { - this.drawable = drawable; - this.title = title; - this.packageName = packageName; - this.activityName = activityName; - } - - public Drawable getDrawable() { - return drawable; - } - - public CharSequence getTitle() { - return title; - } - - public String getPackageName() { - return packageName; - } - - public String getActivityName() { - return activityName; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.kt b/app/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.kt index 75c34009e748..4bf800bc0a24 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.kt @@ -24,14 +24,15 @@ import com.nextcloud.client.utils.IntentUtil.createSendIntent import com.owncloud.android.R import com.owncloud.android.databinding.SendFilesFragmentBinding import com.owncloud.android.datamodel.OCFile -import com.owncloud.android.ui.adapter.SendButtonAdapter -import com.owncloud.android.ui.components.SendButtonData +import com.owncloud.android.ui.adapter.sendButton.SendButtonAdapter +import com.owncloud.android.ui.adapter.sendButton.SendButtonData import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.theme.ViewThemeUtils import javax.inject.Inject class SendFilesDialog : BottomSheetDialogFragment(R.layout.send_files_fragment), + SendButtonAdapter.ClickListener, Injectable { private var files: Array? = null @@ -41,16 +42,18 @@ class SendFilesDialog : @Inject var viewThemeUtils: ViewThemeUtils? = null + private var sendIntent: Intent? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // keep the state of the fragment on configuration changes retainInstance = true files = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - requireArguments().getParcelableArray(KEY_OCFILES, OCFile::class.java) + requireArguments().getParcelableArray(KEY_OC_FILES, OCFile::class.java) } else { @Suppress("DEPRECATION") - requireArguments().getParcelableArray(KEY_OCFILES) as Array? + requireArguments().getParcelableArray(KEY_OC_FILES) as Array? } } @@ -64,7 +67,8 @@ class SendFilesDialog : } private fun setupSendButtonRecyclerView() { - val sendIntent = createSendIntent(requireContext(), files!!) + sendIntent = createSendIntent(requireContext(), files!!) + val sendIntent = sendIntent ?: return val matches = requireActivity().packageManager.queryIntentActivities(sendIntent, 0) if (matches.isEmpty()) { @@ -76,22 +80,12 @@ class SendFilesDialog : } val sendButtonDataList = setupSendButtonData(matches) - val clickListener = setupSendButtonClickListener(sendIntent) @Suppress("MagicNumber") binding.sendButtonRecyclerView.layoutManager = GridLayoutManager(requireActivity(), 4) - binding.sendButtonRecyclerView.adapter = SendButtonAdapter(sendButtonDataList, clickListener) + binding.sendButtonRecyclerView.adapter = SendButtonAdapter(sendButtonDataList, this) } - private fun setupSendButtonClickListener(sendIntent: Intent): SendButtonAdapter.ClickListener = - SendButtonAdapter.ClickListener { sendButtonDataData: SendButtonData -> - val packageName = sendButtonDataData.packageName - val activityName = sendButtonDataData.activityName - sendIntent.component = ComponentName(packageName, activityName) - requireActivity().startActivity(Intent.createChooser(sendIntent, getString(R.string.send))) - dismiss() - } - private fun setupSendButtonData(matches: List): List { var icon: Drawable var sendButtonData: SendButtonData @@ -111,15 +105,25 @@ class SendFilesDialog : return sendButtonDataList } + @Suppress("ReturnCount") + override fun onSendButtonClick(sendButtonData: SendButtonData?) { + sendButtonData ?: return + sendIntent ?: return + + val packageName = sendButtonData.packageName ?: return + val activityName = sendButtonData.activityName ?: return + sendIntent?.component = ComponentName(packageName, activityName) + requireActivity().startActivity(Intent.createChooser(sendIntent, getString(R.string.send))) + dismiss() + } + companion object { - private const val KEY_OCFILES = "KEY_OCFILES" - - fun newInstance(files: Set): SendFilesDialog { - val dialogFragment = SendFilesDialog() - val args = Bundle() - args.putParcelableArray(KEY_OCFILES, files.toTypedArray()) - dialogFragment.arguments = args - return dialogFragment + private const val KEY_OC_FILES = "KEY_OC_FILES" + + fun newInstance(files: Set): SendFilesDialog = SendFilesDialog().apply { + arguments = Bundle().apply { + putParcelableArray(KEY_OC_FILES, files.toTypedArray()) + } } } } diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.kt b/app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.kt index eadb264370f8..21d6c6822842 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.kt @@ -36,8 +36,8 @@ 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.adapter.sendButton.SendButtonAdapter +import com.owncloud.android.ui.adapter.sendButton.SendButtonData import com.owncloud.android.ui.helpers.FileOperationsHelper import com.owncloud.android.utils.MimeTypeUtil import com.owncloud.android.utils.theme.ViewThemeUtils @@ -45,6 +45,7 @@ import javax.inject.Inject class SendShareDialog : BottomSheetDialogFragment(R.layout.send_share_fragment), + SendButtonAdapter.ClickListener, Injectable { private lateinit var binding: SendShareFragmentBinding @@ -59,6 +60,8 @@ class SendShareDialog : @Inject var viewThemeUtils: ViewThemeUtils? = null + private var sendIntent: Intent? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -66,8 +69,8 @@ class SendShareDialog : retainInstance = true val arguments = requireArguments() - file = arguments.getParcelableArgument(KEY_OCFILE, OCFile::class.java) - hideNcSharingOptions = arguments.getBoolean(KEY_HIDE_NCSHARING_OPTIONS, false) + file = arguments.getParcelableArgument(KEY_OC_FILE, OCFile::class.java) + hideNcSharingOptions = arguments.getBoolean(KEY_HIDE_NC_SHARING_OPTIONS, false) sharingPublicPasswordEnforced = arguments.getBoolean(KEY_SHARING_PUBLIC_PASSWORD_ENFORCED, false) sharingPublicAskForPassword = arguments.getBoolean(KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD) } @@ -97,12 +100,11 @@ class SendShareDialog : return } - val sendIntent = createSendIntent(requireContext(), file!!) + sendIntent = createSendIntent(requireContext(), file!!) + val sendIntent = sendIntent ?: return val sendButtonDataList = setupSendButtonData(sendIntent) - val clickListener = setupSendButtonClickListener(sendIntent) - binding.sendButtonRecyclerView.layoutManager = GridLayoutManager(activity, 4) - binding.sendButtonRecyclerView.adapter = SendButtonAdapter(sendButtonDataList, clickListener) + binding.sendButtonRecyclerView.adapter = SendButtonAdapter(sendButtonDataList, this) } private fun setupBottomSheetBehaviour() { @@ -180,28 +182,6 @@ class SendShareDialog : message.show() } - private fun setupSendButtonClickListener(sendIntent: Intent): SendButtonAdapter.ClickListener = - 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 { var icon: Drawable var sendButtonData: SendButtonData @@ -236,33 +216,54 @@ class SendShareDialog : this.fileOperationsHelper = fileOperationsHelper } + @Suppress("ReturnCount") + override fun onSendButtonClick(sendButtonData: SendButtonData?) { + val packageName = sendButtonData?.packageName ?: return + val activityName = sendButtonData.activityName ?: return + + 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() + } + interface SendShareDialogDownloader { fun downloadFile(file: OCFile?, packageName: String?, activityName: String?) } companion object { - private const val KEY_OCFILE = "KEY_OCFILE" + private const val KEY_OC_FILE = "KEY_OC_FILE" 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 const val KEY_HIDE_NC_SHARING_OPTIONS = "KEY_HIDE_NC_SHARING_OPTIONS" private val TAG = SendShareDialog::class.java.simpleName @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 - } + fun newInstance(file: OCFile?, hideNcSharingOptions: Boolean, capability: OCCapability): SendShareDialog = + SendShareDialog().apply { + arguments = Bundle().apply { + putParcelable(KEY_OC_FILE, file) + putBoolean(KEY_HIDE_NC_SHARING_OPTIONS, hideNcSharingOptions) + putBoolean( + KEY_SHARING_PUBLIC_PASSWORD_ENFORCED, + capability.filesSharingPublicPasswordEnforced.isTrue + ) + putBoolean( + KEY_SHARING_PUBLIC_ASK_FOR_PASSWORD, + capability.filesSharingPublicAskForOptionalPassword.isTrue + ) + } + } } } diff --git a/app/src/main/res/layout/send_button.xml b/app/src/main/res/layout/send_button.xml index 539fe52522e0..e27cfeacbdc3 100644 --- a/app/src/main/res/layout/send_button.xml +++ b/app/src/main/res/layout/send_button.xml @@ -1,36 +1,25 @@ - - - + ~ SPDX-License-Identifier: AGPL-3.0-or-later + --> + - - - - - + android:layout_height="@dimen/bottom_sheet_item_height" + android:contentDescription="@string/sendbutton_description" + android:gravity="start|center_vertical" + android:paddingStart="@dimen/standard_padding" + android:paddingEnd="@dimen/standard_padding" + android:text="@string/placeholder_send_button" + android:textColor="@color/text_color" + android:textSize="@dimen/bottom_sheet_text_size" + app:icon="@drawable/ic_launcher_foreground" + app:iconGravity="start" + app:iconPadding="@dimen/standard_padding" + app:iconSize="@dimen/share_icon_size" + app:iconTint="@color/primary" /> From d87f0c7534799f00dd561f32c62f66b83d3ec33e Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 11 Mar 2026 16:59:01 +0100 Subject: [PATCH 2/3] fix layout Signed-off-by: alperozturk96 --- app/src/main/res/layout/send_button.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/res/layout/send_button.xml b/app/src/main/res/layout/send_button.xml index e27cfeacbdc3..1661d3d1a8e3 100644 --- a/app/src/main/res/layout/send_button.xml +++ b/app/src/main/res/layout/send_button.xml @@ -10,16 +10,16 @@ android:id="@+id/send_button" style="@style/Widget.Material3.Button.TextButton" android:layout_width="match_parent" - android:layout_height="@dimen/bottom_sheet_item_height" - android:contentDescription="@string/sendbutton_description" - android:gravity="start|center_vertical" - android:paddingStart="@dimen/standard_padding" - android:paddingEnd="@dimen/standard_padding" - android:text="@string/placeholder_send_button" + android:layout_height="wrap_content" + android:ellipsize="end" + android:gravity="center" + android:maxLines="2" + android:padding="@dimen/standard_half_padding" android:textColor="@color/text_color" android:textSize="@dimen/bottom_sheet_text_size" - app:icon="@drawable/ic_launcher_foreground" - app:iconGravity="start" - app:iconPadding="@dimen/standard_padding" + app:iconGravity="top" + app:iconPadding="@dimen/standard_half_padding" app:iconSize="@dimen/share_icon_size" - app:iconTint="@color/primary" /> + app:iconTint="@null" + tools:icon="@mipmap/ic_launcher" + tools:text="@string/placeholder_send_button" /> From 1d1c75af4110ae86cae147d7d0af8fe7ca997384 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 13 Mar 2026 10:17:09 +0100 Subject: [PATCH 3/3] fix lint Signed-off-by: alperozturk96 --- app/src/main/res/values/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8cd67adcfab4..41a3816a6cfb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -990,7 +990,6 @@ Background operations Show notifications to interact result of background operations Show push notifications sent by the server: Mentions in comments, reception of new remote shares, announcements posted by an admin etc. - Send button icon Uploading files from %1$s to %2$s * Name