diff --git a/app/src/main/java/com/owncloud/android/datamodel/quickPermission/QuickPermissionType.kt b/app/src/main/java/com/owncloud/android/datamodel/quickPermission/QuickPermissionType.kt index d867fb69e0c5..83819443a209 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/quickPermission/QuickPermissionType.kt +++ b/app/src/main/java/com/owncloud/android/datamodel/quickPermission/QuickPermissionType.kt @@ -18,7 +18,7 @@ enum class QuickPermissionType(val iconId: Int, val textId: Int) { VIEW_ONLY(R.drawable.ic_eye, R.string.share_permission_view_only), CAN_EDIT(R.drawable.ic_edit, R.string.share_permission_can_edit), FILE_REQUEST(R.drawable.ic_file_request, R.string.share_permission_file_request), - SECURE_FILE_DROP(R.drawable.ic_file_request, R.string.share_permission_secure_file_drop), + SECURE_FILE_DROP(R.drawable.ic_file_request, R.string.create_end_to_end_encrypted_share), CUSTOM_PERMISSIONS(R.drawable.ic_custom_permissions, R.string.share_custom_permission); fun getText(context: Context): String = context.getString(textId) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/NewSecureFileDropViewHolder.kt b/app/src/main/java/com/owncloud/android/ui/adapter/NewSecureFileDropViewHolder.kt index 0d69f2ca28a8..0e2746288561 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/NewSecureFileDropViewHolder.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/NewSecureFileDropViewHolder.kt @@ -10,15 +10,24 @@ package com.owncloud.android.ui.adapter import android.view.View import androidx.recyclerview.widget.RecyclerView import com.owncloud.android.databinding.FileDetailsShareSecureFileDropAddNewItemBinding +import com.owncloud.android.utils.theme.ViewThemeUtils -internal class NewSecureFileDropViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { +class NewSecureFileDropViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private var binding: FileDetailsShareSecureFileDropAddNewItemBinding? = null + private var viewThemeUtils: ViewThemeUtils? = null - constructor(binding: FileDetailsShareSecureFileDropAddNewItemBinding) : this(binding.root) { + constructor( + binding: FileDetailsShareSecureFileDropAddNewItemBinding, + viewThemeUtils: ViewThemeUtils + ) : this(binding.root) { this.binding = binding + this.viewThemeUtils = viewThemeUtils } fun bind(listener: ShareeListAdapterListener) { - binding!!.addNewSecureFileDrop.setOnClickListener { v: View? -> listener.createSecureFileDrop() } + binding?.addPublicShare?.let { + it.setOnClickListener { listener.createSecureFileDrop() } + viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(it) + } } } diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.kt b/app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.kt index f171602f625c..ef449afabfac 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.kt @@ -77,7 +77,7 @@ class ShareeListAdapter( shareType == ShareType.NEW_PUBLIC_LINK -> { if (encrypted) { val binding = FileDetailsShareSecureFileDropAddNewItemBinding.inflate(inflater, parent, false) - NewSecureFileDropViewHolder(binding) + NewSecureFileDropViewHolder(binding, viewThemeUtils) } else { val binding = FileDetailsSharePublicLinkAddNewItemBinding.inflate(inflater, parent, false) NewLinkShareViewHolder(binding) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java index 48a1ac642937..834278b3b231 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java @@ -51,13 +51,16 @@ import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.SharesType; +import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile; import com.owncloud.android.lib.common.OwnCloudAccount; +import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.NextcloudVersion; import com.owncloud.android.lib.resources.status.OCCapability; +import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.providers.UsersAndGroupsSearchConfig; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; @@ -285,7 +288,16 @@ public void onStop() { searchConfig.reset(); } + private void resetSearchView() { + toggleSearchViewEnable(binding.searchView, true); + binding.searchView.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + binding.searchView.setQueryHint(null); + binding.searchView.setQuery("", false); + binding.pickContactEmailBtn.setVisibility(View.VISIBLE); + } + private void setupView() { + resetSearchView(); setShareWithYou(); OCFile parentFile = fileDataStorageManager.getFileById(file.getParentId()); @@ -321,20 +333,26 @@ private void setupView() { if (file.canReshare() && !FileDetailSharingFragmentHelper.isPublicShareDisabled(capabilities)) { if (file.isEncrypted() || (parentFile != null && parentFile.isEncrypted())) { - if (file.getE2eCounter() == -1) { - // V1 cannot share - binding.searchContainer.setVisibility(View.GONE); - binding.createLink.setVisibility(View.GONE); - } else { - binding.createLink.setText(R.string.add_new_secure_file_drop); - binding.searchView.setQueryHint(getResources().getString(R.string.secure_share_search)); - - if (file.isSharedViaLink()) { - binding.searchView.setQueryHint(getResources().getString(R.string.share_not_allowed_when_file_drop)); - binding.searchView.setInputType(InputType.TYPE_NULL); - disableSearchView(binding.searchView); - } - } + binding.internalShareHeadline.setText(getResources().getString(R.string.internal_share_headline_end_to_end_encrypted)); + binding.internalShareDescription.setVisibility(View.VISIBLE); + binding.externalSharesHeadline.setText(getResources().getString(R.string.create_end_to_end_encrypted_share_title)); + + fetchE2EECounter(() -> { + if (file.getE2eCounter() == -1) { + // V1 cannot share + binding.searchContainer.setVisibility(View.GONE); + binding.createLink.setVisibility(View.GONE); + } else { + binding.createLink.setText(R.string.add_new_secure_file_drop); + binding.searchView.setQueryHint(getResources().getString(R.string.secure_share_search)); + + if (file.isSharedViaLink()) { + binding.searchView.setQueryHint(getResources().getString(R.string.share_not_allowed_when_file_drop)); + binding.searchView.setInputType(InputType.TYPE_NULL); + toggleSearchViewEnable(binding.searchView, false); + } + } + }); } else { binding.createLink.setText(R.string.create_link); binding.searchView.setQueryHint(getResources().getString(R.string.share_search_internal)); @@ -348,7 +366,7 @@ private void setupView() { binding.externalSharesHeadline.setVisibility(View.GONE); binding.searchView.setInputType(InputType.TYPE_NULL); binding.pickContactEmailBtn.setVisibility(View.GONE); - disableSearchView(binding.searchView); + toggleSearchViewEnable(binding.searchView, false); binding.createLink.setOnClickListener(null); } @@ -363,18 +381,34 @@ private void setupView() { ); } + private void fetchE2EECounter(Runnable onComplete) { + new Thread(() -> { + try { + OwnCloudClient client = clientFactory.create(user); + Object metadata = RefreshFolderOperation.getDecryptedFolderMetadata(true, file, client, user, requireContext()); + if (metadata instanceof DecryptedFolderMetadataFile decryptedMetadata) { + file.setE2eCounter(decryptedMetadata.getMetadata().getCounter()); + fileDataStorageManager.saveFile(file); + } + } catch (Exception e) { + Log_OC.e(TAG, "Error refreshing E2E counter: " + e.getMessage()); + } + + requireActivity().runOnUiThread(onComplete); + }).start(); + } + private void checkShareViaUser() { if (!MDMConfig.INSTANCE.shareViaUser(requireContext())) { binding.searchContainer.setVisibility(View.GONE); } } - private void disableSearchView(View view) { - view.setEnabled(false); - + private void toggleSearchViewEnable(View view, boolean enable) { + view.setEnabled(enable); if (view instanceof ViewGroup viewGroup) { for (int i = 0; i < viewGroup.getChildCount(); i++) { - disableSearchView(viewGroup.getChildAt(i)); + toggleSearchViewEnable(viewGroup.getChildAt(i), enable); } } } diff --git a/app/src/main/res/layout/file_details_share_secure_file_drop_add_new_item.xml b/app/src/main/res/layout/file_details_share_secure_file_drop_add_new_item.xml index 420633b1987b..2ab14998d1f7 100644 --- a/app/src/main/res/layout/file_details_share_secure_file_drop_add_new_item.xml +++ b/app/src/main/res/layout/file_details_share_secure_file_drop_add_new_item.xml @@ -2,43 +2,18 @@ - - - - - - - - + ~ SPDX-FileCopyrightText: 2026 Alper Ozturk + ~ SPDX-License-Identifier: AGPL-3.0-or-later + --> + diff --git a/app/src/main/res/layout/file_details_sharing_fragment.xml b/app/src/main/res/layout/file_details_sharing_fragment.xml index 4ee05b28248a..14a056da8f5c 100644 --- a/app/src/main/res/layout/file_details_sharing_fragment.xml +++ b/app/src/main/res/layout/file_details_sharing_fragment.xml @@ -144,6 +144,7 @@ android:text="@string/send_copy_to" /> + + + File request View only Can edit - Secure file drop - + End-to-end encrypted link shares + Link share + End-to-end encrypted shares + Share recipients always have access to the full encrypted folder. It is only possible to share with accounts that have already setup end-to-end encryption. Choose what to sync Free up space %1$s is %2$s, but there is only %3$s available on device.