From 9bf5602c2d6369fbc28c667be02aab6f471f9648 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 15:22:32 +0200 Subject: [PATCH 1/7] refactor(file-actions): unify preview fragments Signed-off-by: alperozturk96 # Conflicts: # app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt --- .../ui/fileactions/FileActionHandler.kt | 11 ++- .../android/ui/fragment/OCFileListFragment.kt | 3 + .../ui/fragment/albums/AlbumItemsFragment.kt | 26 ++++--- .../ui/preview/media/PreviewMediaFragment.kt | 78 +++++++------------ .../preview/media/PreviewPlaybackFragment.kt | 47 +++-------- .../preview/text/PreviewTextFileFragment.java | 53 ++++++------- 6 files changed, 91 insertions(+), 127 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt index 115178418cc6..91d1a83d0606 100644 --- a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt +++ b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt @@ -47,6 +47,10 @@ class FileActionHandler @Inject constructor( when (itemId) { R.id.action_send_share_file -> host.containerActivity.showDetails(file, SHARING_TAB) + R.id.action_see_details -> host.containerActivity.showDetails(file) + + R.id.action_open_file_with -> openFile(file, host) + R.id.action_rename_file -> RenameFileDialogFragment.newInstance(file, host.parentFolder) .show(host.fragmentManager, FileDetailFragment.FTAG_RENAME_FILE) @@ -75,7 +79,7 @@ class FileActionHandler @Inject constructor( .show(host.fragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) R.id.action_cancel_sync -> files.forEach { - host.fda?.cancelTransference(it) + host.fda?.cancelTransference(it) ?: host.helper?.cancelTransference(it) } R.id.action_favorite -> setFavorite(files, true, host) @@ -88,6 +92,11 @@ class FileActionHandler @Inject constructor( return true } + private fun openFile(file: OCFile, host: FileActionHost) { + host.helper?.openFile(file) + host.onFileOpened() + } + private fun setFavorite(files: Collection, isFavorite: Boolean, host: FileActionHost) { host.helper?.toggleFavoriteFiles(files, isFavorite) host.onFavoriteChanged(isFavorite) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.kt index 320cdb5e496d..01f945d5f4bb 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.kt @@ -944,6 +944,9 @@ open class OCFileListFragment : private fun handleListAction(@IdRes itemId: Int, checkedFiles: Set): Boolean { when { + itemId == R.id.action_send_share_file && checkedFiles.size == SINGLE_SELECTION -> + containerActivity?.showDetails(checkedFiles.first(), SHARING_TAB) + itemId == R.id.action_see_details && checkedFiles.size == SINGLE_SELECTION -> showDetailsAndHideSortGroup(checkedFiles.first()) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/albums/AlbumItemsFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/albums/AlbumItemsFragment.kt index 5fab841eb5e6..5e768d1a86be 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/albums/AlbumItemsFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/albums/AlbumItemsFragment.kt @@ -47,6 +47,8 @@ import com.nextcloud.client.utils.IntentUtil import com.nextcloud.client.utils.Throttler import com.nextcloud.repository.ClientRepository import com.nextcloud.ui.albumItemActions.AlbumItemActionsBottomSheet +import com.nextcloud.ui.fileactions.FileActionHandler +import com.nextcloud.ui.fileactions.FileActionHost import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.SnackbarUtil import com.nextcloud.utils.extensions.getTypedActivity @@ -116,6 +118,9 @@ class AlbumItemsFragment : @Inject lateinit var viewThemeUtils: ViewThemeUtils + @Inject + lateinit var fileActionHandler: FileActionHandler + @Inject lateinit var accountManager: UserAccountManager @@ -622,24 +627,21 @@ class AlbumItemsFragment : ?.getClientIntegrationEndpoints(Type.CONTEXT_MENU, checkedFiles.first().mimeType) .orEmpty() - private fun onFileActionChosen(@IdRes itemId: Int, checkedFiles: Set): Boolean { - if (checkedFiles.isEmpty()) { - return false - } - - val fileOperationsHelper = containerActivity?.fileOperationsHelper + private fun onFileActionChosen(@IdRes itemId: Int, checkedFiles: Set) { + if (checkedFiles.isEmpty()) return when (itemId) { R.id.action_remove_file -> confirmFilesRemoval(checkedFiles) - R.id.action_favorite -> fileOperationsHelper?.toggleFavoriteFiles(checkedFiles, true) - R.id.action_unset_favorite -> fileOperationsHelper?.toggleFavoriteFiles(checkedFiles, false) - R.id.action_open_file_with -> fileOperationsHelper?.openFile(checkedFiles.first()) - R.id.action_stream_media -> fileOperationsHelper?.streamMediaFile(checkedFiles.first()) + R.id.action_select_all_action_menu -> selectAllFiles(true) + R.id.action_deselect_all_action_menu -> selectAllFiles(false) - } - return true + else -> containerActivity?.let { + val host = FileActionHost(it, parentFragmentManager, view, null) + fileActionHandler.handle(itemId, checkedFiles, host) + } + } } @Subscribe(threadMode = ThreadMode.BACKGROUND) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt index a5ada2b3d032..f4370b881517 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt @@ -46,11 +46,12 @@ import com.github.chrisbanes.photoview.PhotoView import com.google.android.material.snackbar.Snackbar import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.di.Injectable -import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.player.model.file.PlaybackCollection import com.nextcloud.repository.ClientRepository import com.nextcloud.ui.fileactions.FileAction +import com.nextcloud.ui.fileactions.FileActionHandler +import com.nextcloud.ui.fileactions.FileActionHost import com.nextcloud.ui.fileactions.FileActionsBottomSheet.Companion.newInstance import com.nextcloud.utils.SnackbarUtil import com.nextcloud.utils.extensions.clickWithDebounce @@ -67,8 +68,6 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.operations.FetchRemoteFileOperation import com.owncloud.android.ui.activity.FileActivity -import com.owncloud.android.ui.dialog.ConfirmationDialogFragment -import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment import com.owncloud.android.ui.fragment.FileFragment import com.owncloud.android.utils.BitmapUtils import com.owncloud.android.utils.MimeTypeUtil @@ -99,6 +98,7 @@ import kotlin.math.min * * DO NOT CALL IT: an [OCFile] and [User] must be provided for a successful construction */ +@Suppress("TooManyFunctions") class PreviewMediaFragment : FileFragment(), Injectable { @@ -119,10 +119,10 @@ class PreviewMediaFragment : lateinit var accountManager: UserAccountManager @Inject - lateinit var backgroundJobManager: BackgroundJobManager + lateinit var viewThemeUtils: ViewThemeUtils @Inject - lateinit var viewThemeUtils: ViewThemeUtils + lateinit var fileActionHandler: FileActionHandler private lateinit var binding: PreviewImageFragmentBinding @@ -184,6 +184,7 @@ class PreviewMediaFragment : * {@inheritDoc} */ @Deprecated("Deprecated in Java") + @Suppress("ReturnCount") override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) if (savedInstanceState == null) { @@ -362,6 +363,7 @@ class PreviewMediaFragment : ) } + @Suppress("ReturnCount") private fun onOverflowClick(isManualClick: Boolean = false) { val file = file ?: return val storageManager = containerActivity.storageManager ?: return @@ -416,56 +418,32 @@ class PreviewMediaFragment : .show(fragmentManager, "actions") } - /** - * {@inheritDoc} - */ - @Suppress("CyclomaticComplexMethod") private fun onFileActionChosen(itemId: Int) { - if (itemId == R.id.action_send_share_file) { - if (file.isSharedWithMe && !file.canReshare()) { + val file = file ?: return + val containerActivity = containerActivity ?: return + + when (itemId) { + R.id.action_send_share_file -> if (file.isSharedWithMe && !file.canReshare()) { Snackbar.make(requireView(), R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG).show() } else { containerActivity.fileOperationsHelper.sendShareFile(file) } - } else if (itemId == R.id.action_send_file) { - containerActivity.fileOperationsHelper.sendShareFile(file, true) - } else if (itemId == R.id.action_open_file_with) { - openFile() - } else if (itemId == R.id.action_remove_file) { - val dialog = RemoveFilesDialogFragment.newInstance(file) - dialog.show(parentFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) - } else if (itemId == R.id.action_see_details) { - seeDetails() - } else if (itemId == R.id.action_download_file || itemId == R.id.action_sync_file) { - if (containerActivity is FileActivity) { - val activity = containerActivity as FileActivity - activity.showSyncLoadingDialog(file.isFolder) + + R.id.action_edit -> (requireActivity() as PreviewMediaActivity).startImageEditor(file) + + else -> { + val host = FileActionHost( + containerActivity, + parentFragmentManager, + view, + null, + onFileOpened = ::finish + ) + fileActionHandler.handle(itemId, listOf(file), host) } - containerActivity.fileOperationsHelper.syncFileOrFolder(file) - } else if (itemId == R.id.action_cancel_sync) { - containerActivity.fileOperationsHelper.cancelTransference(file) - } else if (itemId == R.id.action_set_as_wallpaper) { - containerActivity.fileOperationsHelper.setPictureAs(file, imageView) - } else if (itemId == R.id.action_export_file) { - val list = ArrayList() - list.add(file) - containerActivity.fileOperationsHelper.exportFiles( - list, - context, - view, - backgroundJobManager - ) - } else if (itemId == R.id.action_edit) { - (requireActivity() as PreviewMediaActivity).startImageEditor(file) - } else if (itemId == R.id.action_add_to_album) { - containerActivity.fileOperationsHelper.addFileToAlbum(listOf(file)) } } - private fun seeDetails() { - containerActivity.showDetails(file) - } - @SuppressFBWarnings("Dm") override fun onDestroy() { ownedBitmap?.recycle() @@ -475,11 +453,6 @@ class PreviewMediaFragment : /** * Opens the previewed image with an external application. */ - private fun openFile() { - containerActivity.fileOperationsHelper.openFile(file) - finish() - } - @SuppressLint("StaticFieldLeak") private inner class LoadBitmapTask(imageView: PhotoView, infoView: LinearLayout, progressView: FrameLayout) : AsyncTask() { @@ -500,7 +473,7 @@ class PreviewMediaFragment : private var mErrorMessageId = 0 private val paramsLength = 1 - @Suppress("MagicNumber", "LongMethod", "NestedBlockDepth", "CyclomaticComplexMethod") + @Suppress("TooGenericExceptionCaught", "MagicNumber", "ReturnCount", "LongMethod", "NestedBlockDepth") @Deprecated("Deprecated in Java") override fun doInBackground(vararg params: OCFile?): LoadImage? { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE) @@ -652,6 +625,7 @@ class PreviewMediaFragment : } } + @Suppress("ReturnCount") private fun generateCheckerboardLayeredDrawable(result: LoadImage, bitmap: Bitmap?): LayerDrawable { val resources = resources val layers = arrayOfNulls(2) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt index 1f38e0d939d5..24d3f6cb4a34 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt @@ -25,7 +25,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import com.nextcloud.client.account.UserAccountManager -import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.client.player.media3.PlaybackModel import com.nextcloud.client.player.media3.PlaybackQueueLoader import com.nextcloud.client.player.model.PlayerThumbnailLoader @@ -40,6 +39,8 @@ import com.nextcloud.client.player.util.PlayerUtil.isPictureInPictureAllowed import com.nextcloud.client.player.util.PlayerUtil.ownsPlayback import com.nextcloud.client.player.util.PlayerUtil.toPlaybackFile import com.nextcloud.ui.fileactions.FileAction +import com.nextcloud.ui.fileactions.FileActionHandler +import com.nextcloud.ui.fileactions.FileActionHost import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.SnackbarUtil import com.nextcloud.utils.extensions.addPaddingForNavBar @@ -51,8 +52,6 @@ import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.operations.FetchRemoteFileOperation -import com.owncloud.android.ui.dialog.ConfirmationDialogFragment -import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment import com.owncloud.android.utils.MimeTypeUtil import com.owncloud.android.utils.theme.ViewThemeUtils import dagger.android.support.AndroidSupportInjection @@ -96,10 +95,10 @@ class PreviewPlaybackFragment : lateinit var accountManager: UserAccountManager @Inject - lateinit var backgroundJobManager: BackgroundJobManager + lateinit var viewThemeUtils: ViewThemeUtils @Inject - lateinit var viewThemeUtils: ViewThemeUtils + lateinit var fileActionHandler: FileActionHandler private lateinit var binding: PreviewPlaybackFragmentBinding private lateinit var file: OCFile @@ -220,50 +219,26 @@ class PreviewPlaybackFragment : } } - @Suppress("CyclomaticComplexMethod") private fun onFileActionChosen(itemId: Int) { val previewActivity = previewActivity ?: return - val fileOperationsHelper = previewActivity.fileOperationsHelper when (itemId) { - R.id.action_see_details -> previewActivity.showDetails(file) - R.id.action_download_file -> previewActivity.requestForDownload(file) - R.id.action_export_file -> fileOperationsHelper.exportFiles( - arrayListOf(file), - context, - view, - backgroundJobManager - ) - R.id.action_send_share_file -> if (file.isSharedWithMe && !file.canReshare()) { Snackbar.make(requireView(), R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG).show() } else { - fileOperationsHelper.sendShareFile(file) + previewActivity.fileOperationsHelper.sendShareFile(file) } - R.id.action_send_file -> fileOperationsHelper.sendShareFile(file, true) - - R.id.action_open_file_with -> fileOperationsHelper.openFile(file) - - R.id.action_stream_media -> { - playbackModel.pause() - fileOperationsHelper.streamMediaFile(file) - } + else -> { + if (itemId == R.id.action_stream_media || itemId == R.id.action_remove_file) { + playbackModel.pause() + } - R.id.action_remove_file -> { - playbackModel.pause() - RemoveFilesDialogFragment.newInstance( - file - ).show(parentFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) + val host = FileActionHost(previewActivity, parentFragmentManager, view, null) + fileActionHandler.handle(itemId, listOf(file), host) } - - R.id.action_add_to_album -> fileOperationsHelper.addFileToAlbum(listOf(file)) - - R.id.action_lock_file -> fileOperationsHelper.toggleFileLock(file, true) - - R.id.action_unlock_file -> fileOperationsHelper.toggleFileLock(file, false) } } diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java index 845fede2a346..f309a7dcc0f8 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java @@ -20,6 +20,8 @@ import com.nextcloud.client.account.User; import com.nextcloud.ui.fileactions.FileAction; +import com.nextcloud.ui.fileactions.FileActionHandler; +import com.nextcloud.ui.fileactions.FileActionHost; import com.nextcloud.ui.fileactions.FileActionsBottomSheet; import com.nextcloud.utils.SnackbarUtil; import com.nextcloud.utils.extensions.BundleExtensionsKt; @@ -27,10 +29,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.TextEditorWebView; -import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; -import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment; import com.owncloud.android.utils.MimeTypeUtil; import org.mozilla.universalchardet.ReaderFactory; @@ -45,6 +44,10 @@ import java.util.List; import java.util.Scanner; +import javax.inject.Inject; + +import kotlin.Unit; + import androidx.annotation.NonNull; import androidx.appcompat.widget.SearchView; import androidx.core.view.MenuItemCompat; @@ -59,6 +62,8 @@ public class PreviewTextFileFragment extends PreviewTextFragment { private static final String TAG = PreviewTextFileFragment.class.getSimpleName(); + @Inject FileActionHandler fileActionHandler; + private TextLoadAsyncTask textLoadAsyncTask; private User user; @@ -288,30 +293,30 @@ private void showFileActions(OCFile file) { } private void onFileActionChosen(final int itemId) { + final OCFile file = getFile(); + if (file == null) { + return; + } + if (itemId == R.id.action_send_share_file) { - if (getFile().isSharedWithMe() && !getFile().canReshare()) { + if (file.isSharedWithMe() && !file.canReshare()) { SnackbarUtil.show(this, R.string.resharing_is_not_allowed); } else { - containerActivity.getFileOperationsHelper().sendShareFile(getFile()); - } - } else if (itemId == R.id.action_send_file) { - containerActivity.getFileOperationsHelper().sendShareFile(getFile(), true); - } else if (itemId == R.id.action_open_file_with) { - openFile(); - } else if (itemId == R.id.action_remove_file) { - RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile()); - dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); - } else if (itemId == R.id.action_see_details) { - seeDetails(); - } else if (itemId == R.id.action_sync_file) { - if (containerActivity instanceof FileActivity activity) { - activity.showSyncLoadingDialog(getFile().isFolder()); + containerActivity.getFileOperationsHelper().sendShareFile(file); } - containerActivity.getFileOperationsHelper().syncFileOrFolder(getFile()); - } else if(itemId == R.id.action_cancel_sync){ - containerActivity.getFileOperationsHelper().cancelTransference(getFile()); } else if (itemId == R.id.action_edit) { - TextEditorWebView.Companion.startTextEditor(getFile(), getContext()); + TextEditorWebView.Companion.startTextEditor(file, getContext()); + } else { + final var host = new FileActionHost(containerActivity, + getParentFragmentManager(), + getView(), + null, + null, + () -> { + finish(); + return Unit.INSTANCE; + }); + fileActionHandler.handle(itemId, List.of(file), host); } } @@ -324,10 +329,6 @@ public void updateFile(OCFile file) { setFile(file); } - private void seeDetails() { - containerActivity.showDetails(getFile()); - } - /** * Opens the previewed file with an external application. */ From 632396f0f7c7bdf9429b4720af90a5f294e31b2d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 15:59:24 +0200 Subject: [PATCH 2/7] refactor(file-actions): unify preview fragments Signed-off-by: alperozturk96 # Conflicts: # app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java --- .../ui/fileactions/FileActionHandler.kt | 15 +++++-- .../ui/fileactions/FileActionHost.kt | 5 +++ .../FileOperationHelperExtensions.kt | 1 - .../ui/preview/media/PreviewMediaFragment.kt | 22 +--------- .../preview/media/PreviewPlaybackFragment.kt | 7 --- .../preview/text/PreviewTextFileFragment.java | 43 +++++-------------- 6 files changed, 30 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt index 91d1a83d0606..2eabfc2e1499 100644 --- a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt +++ b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHandler.kt @@ -12,6 +12,7 @@ import com.nextcloud.client.editimage.EditImageActivity import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.utils.EditorUtils import com.nextcloud.utils.ShortcutUtil +import com.nextcloud.utils.SnackbarUtil import com.nextcloud.utils.extensions.handle import com.owncloud.android.R import com.owncloud.android.datamodel.OCFile @@ -45,7 +46,7 @@ class FileActionHandler @Inject constructor( @Suppress("CyclomaticComplexMethod") private fun file(@IdRes itemId: Int, file: OCFile, host: FileActionHost): Boolean { when (itemId) { - R.id.action_send_share_file -> host.containerActivity.showDetails(file, SHARING_TAB) + R.id.action_send_share_file -> sendShareFile(file, host) R.id.action_see_details -> host.containerActivity.showDetails(file) @@ -92,6 +93,15 @@ class FileActionHandler @Inject constructor( return true } + private fun sendShareFile(file: OCFile, host: FileActionHost) { + if (file.isSharedWithMe && !file.canReshare()) { + SnackbarUtil.show(host.view, R.string.resharing_is_not_allowed) + return + } + + host.helper?.sendShareFile(file) + } + private fun openFile(file: OCFile, host: FileActionHost) { host.helper?.openFile(file) host.onFileOpened() @@ -109,7 +119,7 @@ class FileActionHandler @Inject constructor( TextEditorWebView.startTextEditor(file, context) EditImageActivity.canBePreviewed(file) -> - host.fda?.startImageEditor(file) + host.fda?.startImageEditor(file) ?: host.previewMediaActivity?.startImageEditor(file) else -> host.helper?.openFileAsRichDocument(file, context) } @@ -150,7 +160,6 @@ class FileActionHandler @Inject constructor( } companion object { - private const val SHARING_TAB = 1 private const val NO_NEUTRAL_BUTTON = -1 } } diff --git a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHost.kt b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHost.kt index 3540e257cf2e..e795cf502841 100644 --- a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHost.kt +++ b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionHost.kt @@ -15,6 +15,7 @@ import com.owncloud.android.ui.activity.FileActivity import com.owncloud.android.ui.activity.FileDisplayActivity import com.owncloud.android.ui.fragment.FileFragment import com.owncloud.android.ui.helpers.FileOperationsHelper +import com.owncloud.android.ui.preview.media.PreviewMediaActivity class FileActionHost @JvmOverloads constructor( val containerActivity: FileFragment.ContainerActivity, @@ -22,6 +23,7 @@ class FileActionHost @JvmOverloads constructor( val view: View?, val parentFolder: OCFile?, val actionMode: ActionMode? = null, + val onFileOpened: () -> Unit = {}, val onFavoriteChanged: (isFavorite: Boolean) -> Unit = {} ) { val helper: FileOperationsHelper? @@ -33,6 +35,9 @@ class FileActionHost @JvmOverloads constructor( val fda: FileDisplayActivity? get() = containerActivity as? FileDisplayActivity + val previewMediaActivity: PreviewMediaActivity? + get() = containerActivity as? PreviewMediaActivity + val context: Context? get() = view?.context } diff --git a/app/src/main/java/com/nextcloud/utils/extensions/FileOperationHelperExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/FileOperationHelperExtensions.kt index 8f5a06143cd1..11cb321b3169 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/FileOperationHelperExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/FileOperationHelperExtensions.kt @@ -17,7 +17,6 @@ import com.owncloud.android.ui.helpers.FileOperationsHelper fun FileOperationsHelper.handle(@IdRes itemId: Int, file: OCFile, view: View?): Boolean { when (itemId) { R.id.action_send_file -> sendShareFile(file, true) - R.id.action_open_file_with -> openFile(file) R.id.action_stream_media -> streamMediaFile(file) R.id.action_set_as_wallpaper -> setPictureAs(file, view) R.id.action_encrypted -> toggleEncryption(file, true) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt index f4370b881517..450609a46370 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt @@ -422,26 +422,8 @@ class PreviewMediaFragment : val file = file ?: return val containerActivity = containerActivity ?: return - when (itemId) { - R.id.action_send_share_file -> if (file.isSharedWithMe && !file.canReshare()) { - Snackbar.make(requireView(), R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG).show() - } else { - containerActivity.fileOperationsHelper.sendShareFile(file) - } - - R.id.action_edit -> (requireActivity() as PreviewMediaActivity).startImageEditor(file) - - else -> { - val host = FileActionHost( - containerActivity, - parentFragmentManager, - view, - null, - onFileOpened = ::finish - ) - fileActionHandler.handle(itemId, listOf(file), host) - } - } + val host = FileActionHost(containerActivity, parentFragmentManager, view, null, onFileOpened = ::finish) + fileActionHandler.handle(itemId, listOf(file), host) } @SuppressFBWarnings("Dm") diff --git a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt index 24d3f6cb4a34..2c30fb8b305b 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewPlaybackFragment.kt @@ -23,7 +23,6 @@ import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope -import com.google.android.material.snackbar.Snackbar import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.player.media3.PlaybackModel import com.nextcloud.client.player.media3.PlaybackQueueLoader @@ -225,12 +224,6 @@ class PreviewPlaybackFragment : when (itemId) { R.id.action_download_file -> previewActivity.requestForDownload(file) - R.id.action_send_share_file -> if (file.isSharedWithMe && !file.canReshare()) { - Snackbar.make(requireView(), R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG).show() - } else { - previewActivity.fileOperationsHelper.sendShareFile(file) - } - else -> { if (itemId == R.id.action_stream_media || itemId == R.id.action_remove_file) { playbackModel.pause() diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java index f309a7dcc0f8..c609c64e4551 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java @@ -23,13 +23,11 @@ import com.nextcloud.ui.fileactions.FileActionHandler; import com.nextcloud.ui.fileactions.FileActionHost; import com.nextcloud.ui.fileactions.FileActionsBottomSheet; -import com.nextcloud.utils.SnackbarUtil; import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.extensions.FileExtensionsKt; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.ui.activity.TextEditorWebView; import com.owncloud.android.utils.MimeTypeUtil; import org.mozilla.universalchardet.ReaderFactory; @@ -46,13 +44,12 @@ import javax.inject.Inject; -import kotlin.Unit; - import androidx.annotation.NonNull; import androidx.appcompat.widget.SearchView; import androidx.core.view.MenuItemCompat; import androidx.fragment.app.FragmentManager; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import kotlin.Unit; public class PreviewTextFileFragment extends PreviewTextFragment { private static final String EXTRA_FILE = "FILE"; @@ -298,26 +295,16 @@ private void onFileActionChosen(final int itemId) { return; } - if (itemId == R.id.action_send_share_file) { - if (file.isSharedWithMe() && !file.canReshare()) { - SnackbarUtil.show(this, R.string.resharing_is_not_allowed); - } else { - containerActivity.getFileOperationsHelper().sendShareFile(file); - } - } else if (itemId == R.id.action_edit) { - TextEditorWebView.Companion.startTextEditor(file, getContext()); - } else { - final var host = new FileActionHost(containerActivity, - getParentFragmentManager(), - getView(), - null, - null, - () -> { - finish(); - return Unit.INSTANCE; - }); - fileActionHandler.handle(itemId, List.of(file), host); - } + final var host = new FileActionHost(containerActivity, + getParentFragmentManager(), + getView(), + null, + null, + () -> { + finish(); + return Unit.INSTANCE; + }); + fileActionHandler.handle(itemId, List.of(file), host); } /** @@ -329,14 +316,6 @@ public void updateFile(OCFile file) { setFile(file); } - /** - * Opens the previewed file with an external application. - */ - private void openFile() { - containerActivity.getFileOperationsHelper().openFile(getFile()); - finish(); - } - /** * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFileFragment} to be previewed. * From 4057b4ccd136919389ec279e539c28be09a4f1f8 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 16:16:13 +0200 Subject: [PATCH 3/7] Rename .java to .kt Signed-off-by: alperozturk96 --- .../{PreviewTextFileFragment.java => PreviewTextFileFragment.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/owncloud/android/ui/preview/text/{PreviewTextFileFragment.java => PreviewTextFileFragment.kt} (100%) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt similarity index 100% rename from app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.java rename to app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt From 9f5dcd71166504a17dc065cc23548ce48bf29707 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 16:16:13 +0200 Subject: [PATCH 4/7] refactor PreviewTextFileFragment convert to kotlin Signed-off-by: alperozturk96 --- .../preview/text/PreviewTextFileFragment.kt | 500 +++++++----------- 1 file changed, 198 insertions(+), 302 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt index c609c64e4551..643fc0fe6dd1 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt @@ -1,352 +1,248 @@ /* * Nextcloud - Android Client * - * SPDX-FileCopyrightText: 2019 Tobias Kaminsky - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH + * SPDX-License-Identifier: AGPL-3.0-or-later */ -package com.owncloud.android.ui.preview.text; - -import android.annotation.SuppressLint; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import com.nextcloud.client.account.User; -import com.nextcloud.ui.fileactions.FileAction; -import com.nextcloud.ui.fileactions.FileActionHandler; -import com.nextcloud.ui.fileactions.FileActionHost; -import com.nextcloud.ui.fileactions.FileActionsBottomSheet; -import com.nextcloud.utils.extensions.BundleExtensionsKt; -import com.nextcloud.utils.extensions.FileExtensionsKt; -import com.owncloud.android.R; -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.utils.MimeTypeUtil; - -import org.mozilla.universalchardet.ReaderFactory; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.io.StringWriter; -import java.lang.ref.WeakReference; -import java.util.LinkedList; -import java.util.List; -import java.util.Scanner; - -import javax.inject.Inject; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.SearchView; -import androidx.core.view.MenuItemCompat; -import androidx.fragment.app.FragmentManager; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import kotlin.Unit; - -public class PreviewTextFileFragment extends PreviewTextFragment { - private static final String EXTRA_FILE = "FILE"; - private static final String EXTRA_USER = "USER"; - private static final String EXTRA_OPEN_SEARCH = "SEARCH"; - private static final String EXTRA_SEARCH_QUERY = "SEARCH_QUERY"; - - private static final String TAG = PreviewTextFileFragment.class.getSimpleName(); - - @Inject FileActionHandler fileActionHandler; - - private TextLoadAsyncTask textLoadAsyncTask; - private User user; - - public static PreviewTextFileFragment create(User user, OCFile file, boolean openSearch, String searchQuery) { - Bundle args = new Bundle(); - args.putParcelable(EXTRA_FILE, file); - args.putParcelable(EXTRA_USER, user); - args.putBoolean(EXTRA_OPEN_SEARCH, openSearch); - args.putString(EXTRA_SEARCH_QUERY, searchQuery); - PreviewTextFileFragment fragment = new PreviewTextFileFragment(); - fragment.setArguments(args); - return fragment; +package com.owncloud.android.ui.preview.text + +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import androidx.annotation.IdRes +import androidx.appcompat.widget.SearchView +import androidx.core.view.MenuProvider +import androidx.core.view.isGone +import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope +import com.nextcloud.client.account.User +import com.nextcloud.ui.fileactions.FileAction +import com.nextcloud.ui.fileactions.FileActionHandler +import com.nextcloud.ui.fileactions.FileActionHost +import com.nextcloud.ui.fileactions.FileActionsBottomSheet +import com.nextcloud.utils.extensions.getParcelableArgument +import com.nextcloud.utils.extensions.logFileSize +import com.owncloud.android.R +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.utils.MimeTypeUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.mozilla.universalchardet.ReaderFactory +import java.io.File +import java.io.IOException +import java.io.Reader +import java.util.Scanner +import javax.inject.Inject + +class PreviewTextFileFragment : PreviewTextFragment() { + + @Inject + lateinit var fileActionHandler: FileActionHandler + + private var textLoadJob: Job? = null + private var user: User? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val args = requireArguments() + readSearchArguments(args) + file = if (savedInstanceState == null) requireFileAndUser(args) else restoreFileAndUser(savedInstanceState) + handler = Handler(Looper.getMainLooper()) } - /** - * Creates an empty fragment for previews. - *

- * MUST BE KEPT: the system uses it when tries to re-instantiate a fragment automatically (for instance, when the - * device is turned a aside). - *

- * DO NOT CALL IT: an {@link OCFile} and {@link User} must be provided for a successful construction - */ - public PreviewTextFileFragment() { - super(); - user = null; + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + addMenuProvider() } - /** - * {@inheritDoc} - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - - OCFile file = getFile(); - - Bundle args = getArguments(); + override fun onSaveInstanceState(outState: Bundle) { + file.logFileSize(TAG) + outState.putParcelable(EXTRA_FILE, file) + outState.putParcelable(EXTRA_USER, user) + super.onSaveInstanceState(outState) + } - if (file == null) { - file = BundleExtensionsKt.getParcelableArgument(args, EXTRA_FILE, OCFile.class); - } + override fun onStop() { + super.onStop() + Log_OC.e(TAG, "onStop") + textLoadJob?.cancel() + } - if (user == null) { - user = BundleExtensionsKt.getParcelableArgument(args, EXTRA_USER, User.class); - } + private fun readSearchArguments(args: Bundle) { + args.getString(EXTRA_SEARCH_QUERY)?.let { searchQuery = it } + searchOpen = args.getBoolean(EXTRA_OPEN_SEARCH, false) + } - if (args.containsKey(EXTRA_SEARCH_QUERY)) { - searchQuery = args.getString(EXTRA_SEARCH_QUERY); + private fun requireFileAndUser(args: Bundle): OCFile { + val previewFile = checkNotNull(file ?: args.getParcelableArgument(EXTRA_FILE, OCFile::class.java)) { + "Instanced with a NULL OCFile" } - searchOpen = args.getBoolean(EXTRA_OPEN_SEARCH, false); - - if (savedInstanceState == null) { - if (file == null) { - throw new IllegalStateException("Instanced with a NULL OCFile"); - } - if (user == null) { - throw new IllegalStateException("Instanced with a NULL ownCloud Account"); - } - } else { - file = BundleExtensionsKt.getParcelableArgument(savedInstanceState, EXTRA_FILE, OCFile.class); - user = BundleExtensionsKt.getParcelableArgument(savedInstanceState, EXTRA_USER, User.class); + user = checkNotNull(user ?: args.getParcelableArgument(EXTRA_USER, User::class.java)) { + "Instanced with a NULL ownCloud Account" } - - handler = new Handler(); - setFile(file); + return previewFile } - /** - * {@inheritDoc} - */ - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - FileExtensionsKt.logFileSize(getFile(), TAG); - outState.putParcelable(PreviewTextFileFragment.EXTRA_FILE, getFile()); - outState.putParcelable(PreviewTextFileFragment.EXTRA_USER, user); - super.onSaveInstanceState(outState); + private fun restoreFileAndUser(savedInstanceState: Bundle): OCFile? { + user = savedInstanceState.getParcelableArgument(EXTRA_USER, User::class.java) + return savedInstanceState.getParcelableArgument(EXTRA_FILE, OCFile::class.java) } - @Override - public void loadAndShowTextPreview() { - textLoadAsyncTask = new TextLoadAsyncTask(new WeakReference<>(binding.textPreview), - new WeakReference<>(binding.emptyListProgress)); - textLoadAsyncTask.execute(getFile().getStoragePath()); - } - - /** - * Reads the file to preview and shows its contents. Too critical to be anonymous. - */ - @SuppressLint("StaticFieldLeak") - private class TextLoadAsyncTask extends AsyncTask { - private static final int PARAMS_LENGTH = 1; - private final WeakReference textViewReference; - private final WeakReference progressViewReference; - - private TextLoadAsyncTask(WeakReference textView, WeakReference progressView) { - textViewReference = textView; - progressViewReference = progressView; + override fun loadAndShowTextPreview() { + val storagePath = file?.storagePath ?: return + textLoadJob = viewLifecycleOwner.lifecycleScope.launch { + val text = withContext(Dispatchers.IO) { readText(storagePath) } + showText(text) } + } - @Override - protected void onPreExecute() { - // not used at the moment + private fun readText(storagePath: String): String { + val text = StringBuilder() + try { + ReaderFactory.createBufferedReader(File(storagePath)).use { text.appendLines(it) } + } catch (e: IOException) { + Log_OC.e(TAG, e.message, e) + finish() } + return text.toString() + } - @Override - protected StringWriter doInBackground(Object... params) { - if (params.length != PARAMS_LENGTH) { - throw new IllegalArgumentException("The parameter to " + TextLoadAsyncTask.class.getName() - + " must be (1) the file location"); - } - String location = (String) params[0]; - - Scanner scanner = null; - StringWriter source = new StringWriter(); - BufferedWriter bufferedWriter = new BufferedWriter(source); - Reader reader = null; - - try { - File file = new File(location); - reader = ReaderFactory.createReaderFromFile(file); - scanner = new Scanner(reader); - - while (scanner.hasNextLine()) { - bufferedWriter.append(scanner.nextLine()); - if (scanner.hasNextLine()) { - bufferedWriter.append("\n"); - } - } - bufferedWriter.close(); - IOException exc = scanner.ioException(); - if (exc != null) { - throw exc; - } - } catch (IOException e) { - Log_OC.e(TAG, e.getMessage(), e); - finish(); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - Log_OC.e(TAG, e.getMessage(), e); - finish(); - } - } - if (scanner != null) { - scanner.close(); - } + private fun StringBuilder.appendLines(reader: Reader) { + val scanner = Scanner(reader) + while (scanner.hasNextLine()) { + append(scanner.nextLine()) + if (scanner.hasNextLine()) { + append(LINE_SEPARATOR) } - return source; } + scanner.ioException()?.let { throw it } + } - @Override - @SuppressFBWarnings("STT") - protected void onPostExecute(final StringWriter stringWriter) { - final TextView textView = textViewReference.get(); + private fun showText(text: String) { + originalText = text + setText(binding.textPreview, text, file, requireActivity(), false, false, viewThemeUtils) - if (textView != null) { - originalText = stringWriter.toString(); - setText(textView, originalText, getFile(), requireActivity(), false, false, viewThemeUtils); + searchView?.let { + it.setOnQueryTextListener(this) + if (searchOpen) { + it.setQuery(searchQuery, true) + } + } - if (searchView != null) { - searchView.setOnQueryTextListener(PreviewTextFileFragment.this); + binding.textPreview.isVisible = true + binding.emptyListProgress.isGone = true + } - if (searchOpen && searchView != null) { - searchView.setQuery(searchQuery, true); - } + private fun addMenuProvider() { + requireActivity().addMenuProvider( + object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + menuInflater.inflate(R.menu.custom_menu_placeholder, menu) + setupSearchView(menu) } - textView.setVisibility(View.VISIBLE); - } + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + if (menuItem.itemId != R.id.custom_menu_placeholder_item) { + return false + } - final FrameLayout progress = progressViewReference.get(); - if (progress != null) { - progress.setVisibility(View.GONE); - } - } + refreshFileAndShowActions() + return true + } + }, + viewLifecycleOwner + ) } - /** - * {@inheritDoc} - */ - @Override - public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.custom_menu_placeholder, menu); + private fun setupSearchView(menu: Menu) { + val searchMenuItem = menu.findItem(R.id.action_search) ?: return + searchMenuItem.isVisible = true + searchView = searchMenuItem.actionView as? SearchView - MenuItem menuItem = menu.findItem(R.id.action_search); - menuItem.setVisible(true); - searchView = (SearchView) MenuItemCompat.getActionView(menuItem); - searchView.setMaxWidth(Integer.MAX_VALUE); - viewThemeUtils.androidx.themeToolbarSearchView(searchView); + val searchView = searchView ?: return + searchView.maxWidth = Int.MAX_VALUE + viewThemeUtils.androidx.themeToolbarSearchView(searchView) if (searchOpen) { - searchView.setIconified(false); - searchView.setQuery(searchQuery, false); - searchView.clearFocus(); - } - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == R.id.custom_menu_placeholder_item) { - final OCFile file = getFile(); - if (containerActivity.getStorageManager() != null && file != null) { - // Update the file - final OCFile updatedFile = containerActivity.getStorageManager().getFileById(file.getFileId()); - setFile(updatedFile); - - final OCFile fileNew = getFile(); - if (fileNew != null) { - showFileActions(file); - } - } - return true; + searchView.isIconified = false + searchView.setQuery(searchQuery, false) + searchView.clearFocus() } - return super.onOptionsItemSelected(item); } - private void showFileActions(OCFile file) { - final var additionalFilter = FileAction.Companion.getFilePreviewActions(getFile()); - final FragmentManager fragmentManager = getChildFragmentManager(); - FileActionsBottomSheet.newInstance(file, false, additionalFilter) - .setResultListener(fragmentManager, this, this::onFileActionChosen) - .show(fragmentManager, "actions"); - } + private fun refreshFileAndShowActions() { + val currentFile = file ?: return + val storageManager = containerActivity?.storageManager ?: return - private void onFileActionChosen(final int itemId) { - final OCFile file = getFile(); - if (file == null) { - return; + file = storageManager.getFileById(currentFile.fileId) + if (file != null) { + showFileActions(currentFile) } - - final var host = new FileActionHost(containerActivity, - getParentFragmentManager(), - getView(), - null, - null, - () -> { - finish(); - return Unit.INSTANCE; - }); - fileActionHandler.handle(itemId, List.of(file), host); } - /** - * Update the file of the fragment with file value - * - * @param file The new file to set - */ - public void updateFile(OCFile file) { - setFile(file); + private fun showFileActions(actionsFile: OCFile) { + val additionalFilter = FileAction.getFilePreviewActions(file) + FileActionsBottomSheet.newInstance(actionsFile, false, additionalFilter) + .setResultListener(childFragmentManager, this) { itemId -> onFileActionChosen(itemId) } + .show(childFragmentManager, TAG_FILE_ACTIONS) } - /** - * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFileFragment} to be previewed. - * - * @param file File to test if can be previewed. - * @return 'True' if the file can be handled by the fragment. - */ - public static boolean canBePreviewed(OCFile file) { - final List unsupportedTypes = new LinkedList<>(); - unsupportedTypes.add("text/richtext"); - unsupportedTypes.add("text/rtf"); - unsupportedTypes.add("text/calendar"); - unsupportedTypes.add("text/vnd.abc"); - unsupportedTypes.add("text/vnd.fmi.flexstor"); - unsupportedTypes.add("text/vnd.rn-realtext"); - unsupportedTypes.add("text/vnd.wap.wml"); - unsupportedTypes.add("text/vnd.wap.wmlscript"); - unsupportedTypes.add("text/html"); - return file != null && file.isDown() && MimeTypeUtil.isText(file) && - !unsupportedTypes.contains(file.getMimeType()) && - !unsupportedTypes.contains(MimeTypeUtil.getMimeTypeFromPath(file.getRemotePath())); + private fun onFileActionChosen(@IdRes itemId: Int) { + val previewFile = file ?: return + val containerActivity = containerActivity ?: return + val host = FileActionHost(containerActivity, parentFragmentManager, view, null, onFileOpened = ::finish) + fileActionHandler.handle(itemId, listOf(previewFile), host) } + fun updateFile(file: OCFile?) { + this.file = file + } - @Override - public void onStop() { - super.onStop(); - Log_OC.e(TAG, "onStop"); + companion object { + private const val EXTRA_FILE = "FILE" + private const val EXTRA_USER = "USER" + private const val EXTRA_OPEN_SEARCH = "SEARCH" + private const val EXTRA_SEARCH_QUERY = "SEARCH_QUERY" + private const val TAG_FILE_ACTIONS = "actions" + private const val LINE_SEPARATOR = "\n" + + private val TAG: String = PreviewTextFileFragment::class.java.simpleName + + private val UNSUPPORTED_MIME_TYPES = setOf( + "text/richtext", + "text/rtf", + "text/calendar", + "text/vnd.abc", + "text/vnd.fmi.flexstor", + "text/vnd.rn-realtext", + "text/vnd.wap.wml", + "text/vnd.wap.wmlscript", + "text/html" + ) + + fun create(user: User, file: OCFile?, openSearch: Boolean, searchQuery: String?): PreviewTextFileFragment = + PreviewTextFileFragment().apply { + arguments = Bundle().apply { + putParcelable(EXTRA_FILE, file) + putParcelable(EXTRA_USER, user) + putBoolean(EXTRA_OPEN_SEARCH, openSearch) + putString(EXTRA_SEARCH_QUERY, searchQuery) + } + } - if (textLoadAsyncTask != null) { - textLoadAsyncTask.cancel(true); - } + fun canBePreviewed(file: OCFile?): Boolean = file != null && + file.isDown && + MimeTypeUtil.isText(file) && + file.mimeType !in UNSUPPORTED_MIME_TYPES && + MimeTypeUtil.getMimeTypeFromPath(file.remotePath) !in UNSUPPORTED_MIME_TYPES } - } From a23160b4e42a15b7b60131e51795e4fc3abeb1a6 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 16:19:32 +0200 Subject: [PATCH 5/7] refactor PreviewTextFileFragment convert to kotlin Signed-off-by: alperozturk96 --- .../owncloud/android/ui/preview/text/PreviewTextFileFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt index 643fc0fe6dd1..a086433ff6f7 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt @@ -65,7 +65,6 @@ class PreviewTextFileFragment : PreviewTextFragment() { } override fun onSaveInstanceState(outState: Bundle) { - file.logFileSize(TAG) outState.putParcelable(EXTRA_FILE, file) outState.putParcelable(EXTRA_USER, user) super.onSaveInstanceState(outState) From b194dee07bc675ca9d10b16c4d242b6ad7ff2ff6 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 22 Oct 2026 16:19:50 +0200 Subject: [PATCH 6/7] refactor PreviewTextFileFragment convert to kotlin Signed-off-by: alperozturk96 --- .../owncloud/android/ui/preview/text/PreviewTextFileFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt index a086433ff6f7..a1937f430f81 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/text/PreviewTextFileFragment.kt @@ -26,7 +26,6 @@ import com.nextcloud.ui.fileactions.FileActionHandler import com.nextcloud.ui.fileactions.FileActionHost import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.extensions.getParcelableArgument -import com.nextcloud.utils.extensions.logFileSize import com.owncloud.android.R import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC From 962de1d4c8c593435ce23848fa9689f1a9e8ec0a Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 26 Oct 2026 17:52:53 +0300 Subject: [PATCH 7/7] wip Signed-off-by: alperozturk96 --- .../owncloud/android/ui/preview/media/PreviewMediaFragment.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt index 450609a46370..8306217a58e4 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/media/PreviewMediaFragment.kt @@ -98,7 +98,6 @@ import kotlin.math.min * * DO NOT CALL IT: an [OCFile] and [User] must be provided for a successful construction */ -@Suppress("TooManyFunctions") class PreviewMediaFragment : FileFragment(), Injectable { @@ -184,7 +183,6 @@ class PreviewMediaFragment : * {@inheritDoc} */ @Deprecated("Deprecated in Java") - @Suppress("ReturnCount") override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) if (savedInstanceState == null) { @@ -363,7 +361,6 @@ class PreviewMediaFragment : ) } - @Suppress("ReturnCount") private fun onOverflowClick(isManualClick: Boolean = false) { val file = file ?: return val storageManager = containerActivity.storageManager ?: return @@ -607,7 +604,6 @@ class PreviewMediaFragment : } } - @Suppress("ReturnCount") private fun generateCheckerboardLayeredDrawable(result: LoadImage, bitmap: Bitmap?): LayerDrawable { val resources = resources val layers = arrayOfNulls(2)