From c3af798233cb2c97c33287f96a7823dec82a608e Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 13:04:48 +0200 Subject: [PATCH 1/4] Rename .java to .kt Signed-off-by: alperozturk96 --- .../android/ui/activity/{ShareActivity.java => ShareActivity.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/owncloud/android/ui/activity/{ShareActivity.java => ShareActivity.kt} (100%) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt similarity index 100% rename from app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java rename to app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt From 1ddae790af2562ac9f27f106e77ad2e5d751a284 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 13:04:49 +0200 Subject: [PATCH 2/4] fix(share-activity): ui/ux Signed-off-by: alperozturk96 --- app/src/main/AndroidManifest.xml | 2 +- .../android/ui/activity/ShareActivity.kt | 293 +++++++++--------- app/src/main/res/layout/share_activity.xml | 14 +- 3 files changed, 158 insertions(+), 151 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0abb03bf8474..7c0a2e60bbf5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -635,7 +635,7 @@ android:exported="false" android:label="@string/share_dialog_title" android:launchMode="singleTop" - android:theme="@style/Theme.ownCloud.Dialog.NoTitle" + android:theme="@style/Theme.ownCloud.Toolbar" android:windowSoftInputMode="adjustResize"> diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt index b7eab1152adc..f16ed1e68ae9 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt @@ -1,6 +1,7 @@ /* * Nextcloud - Android Client * + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2018-2022 Tobias Kaminsky * SPDX-FileCopyrightText: 2019 Chris Narkiewicz * SPDX-FileCopyrightText: 2017 Andy Scherzinger @@ -10,183 +11,177 @@ * SPDX-FileCopyrightText: 2015 MarĂ­a Asensio Valverde * SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only) */ -package com.owncloud.android.ui.activity; - -import android.app.Activity; -import android.graphics.Bitmap; -import android.graphics.drawable.LayerDrawable; -import android.os.Bundle; - -import com.nextcloud.client.account.User; -import com.owncloud.android.R; -import com.owncloud.android.databinding.ShareActivityBinding; -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.datamodel.SyncedFolderObserver; -import com.owncloud.android.datamodel.SyncedFolderProvider; -import com.owncloud.android.datamodel.ThumbnailsCacheManager; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; -import com.owncloud.android.lib.resources.files.model.RemoteFile; -import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.operations.GetSharesForFileOperation; -import com.owncloud.android.ui.fragment.FileDetailSharingFragment; -import com.owncloud.android.ui.fragment.FileDetailsSharingProcessFragment; -import com.owncloud.android.utils.DisplayUtils; -import com.owncloud.android.utils.MimeTypeUtil; - -import java.util.Optional; - -import javax.inject.Inject; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; - -/** - * Activity for sharing files. - */ -public class ShareActivity extends FileActivity { +package com.owncloud.android.ui.activity + +import android.content.Intent +import android.os.Bundle +import androidx.lifecycle.lifecycleScope +import com.nextcloud.client.account.User +import com.owncloud.android.R +import com.owncloud.android.databinding.ShareActivityBinding +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.datamodel.SyncedFolderObserver +import com.owncloud.android.datamodel.ThumbnailsCacheManager +import com.owncloud.android.lib.common.operations.RemoteOperation +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation +import com.owncloud.android.lib.resources.files.model.RemoteFile +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.operations.GetSharesForFileOperation +import com.owncloud.android.ui.fragment.FileDetailSharingFragment +import com.owncloud.android.ui.fragment.FileDetailsSharingProcessFragment +import com.owncloud.android.utils.DisplayUtils +import com.owncloud.android.utils.MimeTypeUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class ShareActivity : FileActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val binding = ShareActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + val currentUser = user.orElse(null) ?: run { + finish() + return + } + val file = file ?: run { + finish() + return + } + + setupHeader(binding, file, currentUser) + fetchRemoteFileSize(file, currentUser, binding) - private static final String TAG = ShareActivity.class.getSimpleName(); + if (savedInstanceState == null) { + showSharingFragment(file, currentUser) + } + } - static final String TAG_SHARE_FRAGMENT = "SHARE_FRAGMENT"; + override fun onStart() { + super.onStart() + Log_OC.d(TAG, "Refreshing lists on account set") + refreshSharesFromStorageManager() + } - @Inject - SyncedFolderProvider syncedFolderProvider; + override fun doShareWith(shareeName: String, shareType: ShareType) { + val file = file ?: return + supportFragmentManager.beginTransaction() + .replace( + R.id.share_fragment_container, + FileDetailsSharingProcessFragment.newInstance(file, shareeName, shareType, false), + FileDetailsSharingProcessFragment.TAG + ) + .commit() + } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + override fun onRemoteOperationFinish(operation: RemoteOperation<*>?, result: RemoteOperationResult<*>) { + super.onRemoteOperationFinish(operation, result) - ShareActivityBinding binding = ShareActivityBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); + val isShareNotFound = operation is GetSharesForFileOperation && + result.code == RemoteOperationResult.ResultCode.SHARE_NOT_FOUND - OCFile file = getFile(); - Optional optionalUser = getUser(); - if (optionalUser.isEmpty()) { - finish(); - return; + if (result.isSuccess || isShareNotFound) { + Log_OC.d(TAG, "Refreshing view on successful operation or finished refresh") + refreshSharesFromStorageManager() } + } + + override fun onShareProcessClosed() { + finish() + } - // Icon - if (file.isFolder()) { - boolean isAutoUploadFolder = SyncedFolderObserver.INSTANCE.isAutoUploadFolder(file, optionalUser.get()); + private fun setupHeader(binding: ShareActivityBinding, file: OCFile, user: User) { + binding.shareBackButton.setOnClickListener { navigateToParentFolder(user) } + setupFileIcon(binding, file, user) + with(binding) { + shareFileName.text = getString(R.string.share_file, file.fileName) + viewThemeUtils.platform.colorViewBackground(shareHeaderDivider) + shareFileSize.text = DisplayUtils.bytesToHumanReadable(file.fileLength) + } + } - Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder); - LayerDrawable drawable = MimeTypeUtil.getFolderIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils); - binding.shareFileIcon.setImageDrawable(drawable); + private fun setupFileIcon(binding: ShareActivityBinding, file: OCFile, user: User) { + if (file.isFolder) { + val isAutoUploadFolder = SyncedFolderObserver.isAutoUploadFolder(file, user) + val overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder) + binding.shareFileIcon.setImageDrawable( + MimeTypeUtil.getFolderIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils) + ) } else { - binding.shareFileIcon.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimeType(), - file.getFileName(), - this, - viewThemeUtils)); + binding.shareFileIcon.setImageDrawable( + MimeTypeUtil.getFileTypeIcon(file.mimeType, file.fileName, this, viewThemeUtils) + ) if (MimeTypeUtil.isImage(file)) { - String remoteId = String.valueOf(file.getRemoteId()); - Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(remoteId); - if (thumbnail != null) { - binding.shareFileIcon.setImageBitmap(thumbnail); + ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId.toString())?.let { + binding.shareFileIcon.setImageBitmap(it) } } } + } - // Name - binding.shareFileName.setText(getResources().getString(R.string.share_file, file.getFileName())); - - viewThemeUtils.platform.colorViewBackground(binding.shareHeaderDivider); - - // Size - binding.shareFileSize.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength())); - - Activity activity = this; - new Thread(() -> { - RemoteOperationResult result = new ReadFileRemoteOperation(getFile().getRemotePath()) - .execute(optionalUser.get(), - activity); - - if (result.isSuccess()) { - RemoteFile remoteFile = (RemoteFile) result.getData().get(0); - long length = remoteFile.getLength(); - - getFile().setFileLength(length); - runOnUiThread(() -> binding.shareFileSize.setText(DisplayUtils.bytesToHumanReadable(length))); + private fun fetchRemoteFileSize(file: OCFile, user: User, binding: ShareActivityBinding) { + lifecycleScope.launch(Dispatchers.IO) { + val result = ReadFileRemoteOperation(file.remotePath).execute(user, this@ShareActivity) + if (result.isSuccess) { + val length = (result.data.first() as RemoteFile).length + file.fileLength = length + withContext(Dispatchers.Main) { + binding.shareFileSize.text = DisplayUtils.bytesToHumanReadable(length) + } } - }).start(); - - if (savedInstanceState == null) { - // Add Share fragment on first creation - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - Fragment fragment = FileDetailSharingFragment.newInstance(getFile(), optionalUser.get()); - ft.replace(R.id.share_fragment_container, fragment, TAG_SHARE_FRAGMENT); - ft.commit(); } } - @Override - protected void onStart() { - super.onStart(); - - // Load data into the list - Log_OC.d(TAG, "Refreshing lists on account set"); - refreshSharesFromStorageManager(); - } - - @Override - protected void doShareWith(String shareeName, ShareType shareType) { - getSupportFragmentManager().beginTransaction().replace(R.id.share_fragment_container, - FileDetailsSharingProcessFragment.newInstance(getFile(), - shareeName, - shareType, - false), - FileDetailsSharingProcessFragment.TAG) - .commit(); + private fun showSharingFragment(file: OCFile, user: User) { + val fragment = FileDetailSharingFragment.newInstance(file, user) + supportFragmentManager.beginTransaction() + .replace(R.id.share_fragment_container, fragment, TAG_SHARE_FRAGMENT) + .commit() } - /** - * Updates the view associated to the activity after the finish of some operation over files in the current - * account. - * - * @param operation Removal operation performed. - * @param result Result of the removal. - */ - @Override - public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { - super.onRemoteOperationFinish(operation, result); - - if (result.isSuccess() || - (operation instanceof GetSharesForFileOperation && - result.getCode() == RemoteOperationResult.ResultCode.SHARE_NOT_FOUND - ) - ) { - Log_OC.d(TAG, "Refreshing view on successful operation or finished refresh"); - refreshSharesFromStorageManager(); + private fun refreshSharesFromStorageManager() { + shareFileFragment?.takeIf { it.isAdded }?.run { + refreshCapabilitiesFromDB() + refreshSharesFromDB() } } - /** - * Updates the view, reading data from {@link com.owncloud.android.datamodel.FileDataStorageManager}. - */ - private void refreshSharesFromStorageManager() { + private val shareFileFragment: FileDetailSharingFragment? + get() = supportFragmentManager.findFragmentByTag(TAG_SHARE_FRAGMENT) as? FileDetailSharingFragment - FileDetailSharingFragment shareFileFragment = getShareFileFragment(); - if (shareFileFragment != null - && shareFileFragment.isAdded()) { // only if added to the view hierarchy!! - shareFileFragment.refreshCapabilitiesFromDB(); - shareFileFragment.refreshSharesFromDB(); + private fun navigateToParentFolder(user: User) { + val file = file ?: run { + finish() + return + } + val parentFolder = if (file.isFolder) { + file + } else { + storageManager.getFileByDecryptedRemotePath(file.parentRemotePath) + } + + if (parentFolder == null) { + finish() + return } - } - /** - * Shortcut to get access to the {@link FileDetailSharingFragment} instance, if any - * - * @return A {@link FileDetailSharingFragment} instance, or null - */ - private FileDetailSharingFragment getShareFileFragment() { - return (FileDetailSharingFragment) getSupportFragmentManager().findFragmentByTag(TAG_SHARE_FRAGMENT); + Intent(this, FileDisplayActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + putExtra(EXTRA_FILE, parentFolder) + putExtra(EXTRA_USER, user) + }.also { + startActivity(it) + finish() + } } - @Override - public void onShareProcessClosed() { - finish(); + companion object { + private val TAG: String = ShareActivity::class.java.simpleName + const val TAG_SHARE_FRAGMENT: String = "SHARE_FRAGMENT" } } diff --git a/app/src/main/res/layout/share_activity.xml b/app/src/main/res/layout/share_activity.xml index 94ec5f013606..244ed606b28e 100644 --- a/app/src/main/res/layout/share_activity.xml +++ b/app/src/main/res/layout/share_activity.xml @@ -21,12 +21,24 @@ android:layout_height="wrap_content" android:padding="@dimen/standard_padding"> + + From 979cdb39a33312fece764d522a019cfd998cf275 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 13:13:54 +0200 Subject: [PATCH 3/4] fix(share-activity): ui/ux Signed-off-by: alperozturk96 --- .../android/ui/activity/ShareActivity.kt | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt index f16ed1e68ae9..35b0ddbbf7ad 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt @@ -16,12 +16,14 @@ package com.owncloud.android.ui.activity import android.content.Intent import android.os.Bundle import androidx.lifecycle.lifecycleScope +import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.client.account.User +import com.nextcloud.client.di.Injectable import com.owncloud.android.R import com.owncloud.android.databinding.ShareActivityBinding import com.owncloud.android.datamodel.OCFile import com.owncloud.android.datamodel.SyncedFolderObserver -import com.owncloud.android.datamodel.ThumbnailsCacheManager +import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC @@ -33,11 +35,21 @@ import com.owncloud.android.ui.fragment.FileDetailSharingFragment import com.owncloud.android.ui.fragment.FileDetailsSharingProcessFragment import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.MimeTypeUtil +import com.owncloud.android.utils.overlay.OverlayManager +import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -class ShareActivity : FileActivity() { +class ShareActivity : + FileActivity(), + Injectable { + + @Inject + lateinit var syncedFolderProvider: SyncedFolderProvider + + @Inject + lateinit var overlayManager: OverlayManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -97,6 +109,7 @@ class ShareActivity : FileActivity() { private fun setupHeader(binding: ShareActivityBinding, file: OCFile, user: User) { binding.shareBackButton.setOnClickListener { navigateToParentFolder(user) } + viewThemeUtils.platform.colorImageView(binding.shareBackButton, ColorRole.ON_SURFACE) setupFileIcon(binding, file, user) with(binding) { shareFileName.text = getString(R.string.share_file, file.fileName) @@ -113,14 +126,19 @@ class ShareActivity : FileActivity() { MimeTypeUtil.getFolderIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils) ) } else { - binding.shareFileIcon.setImageDrawable( - MimeTypeUtil.getFileTypeIcon(file.mimeType, file.fileName, this, viewThemeUtils) + DisplayUtils.setThumbnail( + file, + binding.shareFileIcon, + user, + storageManager, + mutableListOf(), + false, + this, + null, + preferences, + viewThemeUtils, + overlayManager ) - if (MimeTypeUtil.isImage(file)) { - ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId.toString())?.let { - binding.shareFileIcon.setImageBitmap(it) - } - } } } From 4d4211eedfd9d019f806cc9730b7eb46ab8820b5 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 13:14:09 +0200 Subject: [PATCH 4/4] fix(share-activity): ui/ux Signed-off-by: alperozturk96 --- .../java/com/owncloud/android/ui/activity/ShareActivity.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt index 35b0ddbbf7ad..001003afa090 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.kt @@ -123,7 +123,12 @@ class ShareActivity : val isAutoUploadFolder = SyncedFolderObserver.isAutoUploadFolder(file, user) val overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder) binding.shareFileIcon.setImageDrawable( - MimeTypeUtil.getFolderIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils) + MimeTypeUtil.getFolderIcon( + preferences.isDarkModeEnabled(), + overlayIconId, + this, + viewThemeUtils + ) ) } else { DisplayUtils.setThumbnail(