From 2272935751c9ac67014b23c978ed310f07c8b32b Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 4 Mar 2026 16:13:12 +0100 Subject: [PATCH 1/4] fix/file-download-fragment-visibility Signed-off-by: alperozturk96 # Conflicts: # app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.java --- .../res/layout/file_download_fragment.xml | 164 ++++++++++++------ app/src/main/res/values/dims.xml | 2 + 2 files changed, 111 insertions(+), 55 deletions(-) diff --git a/app/src/main/res/layout/file_download_fragment.xml b/app/src/main/res/layout/file_download_fragment.xml index ee6b760aded4..7ecfa841bc8e 100644 --- a/app/src/main/res/layout/file_download_fragment.xml +++ b/app/src/main/res/layout/file_download_fragment.xml @@ -1,75 +1,129 @@ - - - - - + android:clickable="true" + android:focusable="true"> - - + + + app:cardCornerRadius="@dimen/standard_padding" + app:cardElevation="0dp" + app:strokeWidth="0dp"> + + + + + + + + + + + + + + - + + + + + android:layout_marginTop="@dimen/standard_margin" + app:cardCornerRadius="@dimen/card_corner_radius" + app:cardElevation="0dp" + app:strokeWidth="0dp"> - + - - - + + + + + + + + + - + diff --git a/app/src/main/res/values/dims.xml b/app/src/main/res/values/dims.xml index d021ac9ac1c1..4c1368eae716 100644 --- a/app/src/main/res/values/dims.xml +++ b/app/src/main/res/values/dims.xml @@ -26,7 +26,9 @@ 512 28dp 16dp + 16dp 32dp + 64dp 8dp 4dp 32dp From 3dca4d72e2c122a64736ed468f018f1652d9578c Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 4 Mar 2026 16:24:57 +0100 Subject: [PATCH 2/4] Rename .java to .kt Signed-off-by: alperozturk96 --- .../{FileDownloadFragment.java => FileDownloadFragment.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/owncloud/android/ui/preview/{FileDownloadFragment.java => FileDownloadFragment.kt} (100%) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.java b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt similarity index 100% rename from app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.java rename to app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt From 9d1c5ae6bdb1097aee43fb576b5e03ef4d559b0b Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 4 Mar 2026 16:24:57 +0100 Subject: [PATCH 3/4] fix Signed-off-by: alperozturk96 --- .../ui/preview/FileDownloadFragment.kt | 342 +++++++----------- 1 file changed, 128 insertions(+), 214 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt index 5223a8520ed1..811306258008 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt @@ -1,7 +1,7 @@ /* * Nextcloud - Android Client * - * SPDX-FileCopyrightText: 2023 Alper Ozturk + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2022 Álvaro Brey * SPDX-FileCopyrightText: 2022 Tobias Kaminsky * SPDX-FileCopyrightText: 2020 Chris Narkiewicz @@ -10,257 +10,171 @@ * SPDX-FileCopyrightText: 2013-2015 David A. Velasco * SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only) */ -package com.owncloud.android.ui.preview; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.nextcloud.client.account.User; -import com.nextcloud.client.di.Injectable; -import com.nextcloud.client.jobs.download.FileDownloadHelper; -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.adapter.progressListener.DownloadProgressListener; -import com.owncloud.android.ui.fragment.FileFragment; -import com.owncloud.android.utils.theme.ViewThemeUtils; - -import javax.inject.Inject; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -/** - * This Fragment is used to monitor the progress of a file downloading. - */ -public class FileDownloadFragment extends FileFragment implements OnClickListener, Injectable { - - public static final String EXTRA_FILE = "FILE"; - public static final String EXTRA_USER = "USER"; - private static final String EXTRA_ERROR = "ERROR"; - - private static final String ARG_FILE = "FILE"; - private static final String ARG_IGNORE_FIRST = "IGNORE_FIRST"; - private static final String ARG_USER = "USER"; - - private View mView; - private User user; - - @Inject ViewThemeUtils viewThemeUtils; - public DownloadProgressListener mProgressListener; - private boolean mListening; - - private static final String TAG = FileDownloadFragment.class.getSimpleName(); - - private boolean mIgnoreFirstSavedState; - private boolean mError; - - - /** - * Public factory method to create a new fragment that shows the progress of a file download. - *

- * Android strongly recommends keep the empty constructor of fragments as the only public constructor, and - * use {@link #setArguments(Bundle)} to set the needed arguments. - *

- * This method hides to client objects the need of doing the construction in two steps. - *

- * When 'file' is null creates a dummy layout (useful when a file wasn't tapped before). - * - * @param file An {@link OCFile} to show in the fragment - * @param user Nextcloud user; needed to start downloads - * @param ignoreFirstSavedState Flag to work around an unexpected behaviour - * TODO better solution - */ - public static Fragment newInstance(OCFile file, User user, boolean ignoreFirstSavedState) { - FileDownloadFragment frag = new FileDownloadFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_FILE, file); - args.putParcelable(ARG_USER, user); - args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState); - frag.setArguments(args); - return frag; - } - - - /** - * Creates an empty details fragment. - *

- * It's necessary to keep a public constructor without parameters; the system uses it when tries to - * re-instantiate a fragment automatically. - */ - public FileDownloadFragment() { - super(); - mProgressListener = null; - mListening = false; - mIgnoreFirstSavedState = false; - mError = false; - } - - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle args = getArguments(); - if (args == null) { - return; +package com.owncloud.android.ui.preview + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.nextcloud.client.account.User +import com.nextcloud.client.di.Injectable +import com.nextcloud.client.jobs.download.FileDownloadHelper.Companion.instance +import com.nextcloud.utils.extensions.getParcelableArgument +import com.nextcloud.utils.extensions.getTypedActivity +import com.owncloud.android.R +import com.owncloud.android.databinding.FileDownloadFragmentBinding +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.ui.adapter.progressListener.DownloadProgressListener +import com.owncloud.android.ui.fragment.FileFragment +import com.owncloud.android.utils.theme.ViewThemeUtils +import javax.inject.Inject + +class FileDownloadFragment : + FileFragment(), + View.OnClickListener, + Injectable { + private var user: User? = null + private var _binding: FileDownloadFragmentBinding? = null + private val binding get() = _binding!! + + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + + var progressListener: DownloadProgressListener? = null + private var listening = false + private var ignoreFirstSavedState = false + private var downloadError = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.let { + file = it.getParcelableArgument(ARG_FILE, OCFile::class.java) + ignoreFirstSavedState = it.getBoolean(ARG_IGNORE_FIRST) + user = it.getParcelableArgument(ARG_USER, User::class.java) } - - setFile(BundleExtensionsKt.getParcelableArgument(args, ARG_FILE, OCFile.class)); - // TODO better in super, but needs to check ALL the class extending FileFragment; not right now - - mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST); - user = BundleExtensionsKt.getParcelableArgument(args, ARG_USER, User.class); } - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + super.onCreateView(inflater, container, savedInstanceState) - if (getArguments() != null) { - if (!mIgnoreFirstSavedState) { - setFile(BundleExtensionsKt.getParcelableArgument(requireArguments(), EXTRA_FILE, OCFile.class)); - user = BundleExtensionsKt.getParcelableArgument(requireArguments(), EXTRA_USER, User.class); - mError = requireArguments().getBoolean(EXTRA_ERROR); - FileDownloadHelper.Companion.instance().downloadFile(user, getFile()); - } - else { - mIgnoreFirstSavedState = false; - } + if (!ignoreFirstSavedState) { + downloadError = requireArguments().getBoolean(EXTRA_ERROR) + instance().downloadFile(user!!, file) + } else { + ignoreFirstSavedState = false } - mView = inflater.inflate(R.layout.file_download_fragment, container, false); - - ProgressBar progressBar = mView.findViewById(R.id.progressBar); - viewThemeUtils.platform.themeHorizontalProgressBar(progressBar); - mProgressListener = new DownloadProgressListener(progressBar); + _binding = FileDownloadFragmentBinding.inflate(inflater, container, false) - (mView.findViewById(R.id.cancelBtn)).setOnClickListener(this); + viewThemeUtils.material.run { + colorProgressBar(binding.progressBar) + colorMaterialTextButton(binding.cancelBtn) + themeCardView(binding.progressCard) + themeCardView(binding.errorCard) + } - (mView.findViewById(R.id.fileDownloadLL)).setOnClickListener(v -> { - if (getActivity() instanceof PreviewImageActivity previewImageActivity) { - previewImageActivity.toggleFullScreen(); - } - }); + progressListener = DownloadProgressListener(binding.progressBar) - if (mError) { - setButtonsForRemote(); - } - else { - setButtonsForTransferring(); + binding.cancelBtn.setOnClickListener(this) + binding.fileDownloadLL.setOnClickListener { + getTypedActivity(PreviewImageActivity::class.java)?.toggleFullScreen() } - return mView; - } + setButtonsForTransferring(isTransferring = !downloadError) - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - FileExtensionsKt.logFileSize(getFile(), TAG); - outState.putParcelable(FileDownloadFragment.EXTRA_FILE, getFile()); - outState.putParcelable(FileDownloadFragment.EXTRA_USER, user); - outState.putBoolean(FileDownloadFragment.EXTRA_ERROR, mError); + return binding.root } - @Override - public void onStart() { - super.onStart(); - listenForTransferProgress(); + override fun onDestroyView() { + super.onDestroyView() + _binding = null } - @Override - public void onStop() { - leaveTransferProgress(); - super.onStop(); + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.run { + putParcelable(EXTRA_FILE, file) + putParcelable(EXTRA_USER, user) + putBoolean(EXTRA_ERROR, downloadError) + } } - @Override - public View getView() { - if (!mListening) { - listenForTransferProgress(); - } - return super.getView() == null ? mView : super.getView(); + override fun onStart() { + super.onStart() + listenForTransferProgress() } + override fun onStop() { + leaveTransferProgress() + super.onStop() + } - @Override - public void onClick(View v) { - if (v.getId() == R.id.cancelBtn) { - containerActivity.getFileOperationsHelper().cancelTransference(getFile()); - requireActivity().finish(); + override fun onClick(v: View) { + if (v.id == R.id.cancelBtn) { + containerActivity.getFileOperationsHelper().cancelTransference(file) + requireActivity().finish() } else { - Log_OC.e(TAG, "Incorrect view clicked!"); + Log_OC.e(TAG, "Incorrect view clicked!") } } + private fun setButtonsForTransferring(isTransferring: Boolean) { + val binding = _binding ?: return - /** - * Enables or disables buttons for a file being downloaded - */ - private void setButtonsForTransferring() { - if (getView() == null) { - return; - } + val transferringVisibility = if (isTransferring) View.VISIBLE else View.GONE + val remoteVisibility = if (isTransferring) View.GONE else View.VISIBLE - getView().findViewById(R.id.cancelBtn).setVisibility(View.VISIBLE); + binding.run { + downloadingContainer.visibility = transferringVisibility + errorContainer.visibility = remoteVisibility - // show the progress bar for the transfer - getView().findViewById(R.id.progressBar).setVisibility(View.VISIBLE); - TextView progressText = getView().findViewById(R.id.progressText); - progressText.setText(R.string.downloader_download_in_progress_ticker); - progressText.setVisibility(View.VISIBLE); - - // hides the error icon - getView().findViewById(R.id.errorText).setVisibility(View.GONE); - getView().findViewById(R.id.error_image).setVisibility(View.GONE); - } - - /** - * Enables or disables buttons for a file not locally available - *

- * Currently, this is only used when a download was failed - */ - private void setButtonsForRemote() { - if (getView() == null) { - return; + progressText.apply { + setText(R.string.downloader_download_in_progress_ticker) + visibility = transferringVisibility + } } + } - getView().findViewById(R.id.cancelBtn).setVisibility(View.GONE); - - // hides the progress bar and message - getView().findViewById(R.id.progressBar).setVisibility(View.GONE); - getView().findViewById(R.id.progressText).setVisibility(View.GONE); + fun listenForTransferProgress() { + val listener = containerActivity.getFileDownloadProgressListener() ?: return + if (progressListener == null || listening) return - // shows the error icon and message - getView().findViewById(R.id.errorText).setVisibility(View.VISIBLE); - getView().findViewById(R.id.error_image).setVisibility(View.VISIBLE); + listener.addDataTransferProgressListener(progressListener, file) + listening = true + setButtonsForTransferring(isTransferring = true) } + fun leaveTransferProgress() { + val listener = containerActivity.getFileDownloadProgressListener() ?: return + if (progressListener == null) return - public void listenForTransferProgress() { - if (mProgressListener != null && !mListening && containerActivity.getFileDownloadProgressListener() != null) { - containerActivity.getFileDownloadProgressListener().addDataTransferProgressListener(mProgressListener, getFile()); - mListening = true; - setButtonsForTransferring(); - } + listener.removeDataTransferProgressListener(progressListener, file) + listening = false } - - public void leaveTransferProgress() { - if (mProgressListener != null && containerActivity.getFileDownloadProgressListener() != null) { - containerActivity.getFileDownloadProgressListener() - .removeDataTransferProgressListener(mProgressListener, getFile()); - mListening = false; - } + fun setError(error: Boolean) { + downloadError = error } - public void setError(boolean error) { - mError = error; + companion object { + const val EXTRA_FILE: String = "FILE" + const val EXTRA_USER: String = "USER" + private const val EXTRA_ERROR = "ERROR" + private const val ARG_FILE = "FILE" + private const val ARG_IGNORE_FIRST = "IGNORE_FIRST" + private const val ARG_USER = "USER" + private val TAG: String = FileDownloadFragment::class.java.simpleName + + fun newInstance(file: OCFile?, user: User?, ignoreFirstSavedState: Boolean): Fragment = + FileDownloadFragment().apply { + arguments = Bundle().apply { + putParcelable(ARG_FILE, file) + putParcelable(ARG_USER, user) + putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState) + } + } } } From 74c990731cac1265d4f20100290159fd7637cbfa Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 5 Mar 2026 08:24:44 +0100 Subject: [PATCH 4/4] indeterminate progress bar since download listener is broken due to worker migration Signed-off-by: alperozturk96 --- .../ui/preview/FileDownloadFragment.kt | 32 ------------------- .../res/layout/file_download_fragment.xml | 6 ++-- app/src/main/res/values/dims.xml | 2 +- 3 files changed, 4 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt index 811306258008..6fd02e267043 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt @@ -27,7 +27,6 @@ import com.owncloud.android.R import com.owncloud.android.databinding.FileDownloadFragmentBinding import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC -import com.owncloud.android.ui.adapter.progressListener.DownloadProgressListener import com.owncloud.android.ui.fragment.FileFragment import com.owncloud.android.utils.theme.ViewThemeUtils import javax.inject.Inject @@ -43,8 +42,6 @@ class FileDownloadFragment : @Inject lateinit var viewThemeUtils: ViewThemeUtils - var progressListener: DownloadProgressListener? = null - private var listening = false private var ignoreFirstSavedState = false private var downloadError = false @@ -76,8 +73,6 @@ class FileDownloadFragment : themeCardView(binding.errorCard) } - progressListener = DownloadProgressListener(binding.progressBar) - binding.cancelBtn.setOnClickListener(this) binding.fileDownloadLL.setOnClickListener { getTypedActivity(PreviewImageActivity::class.java)?.toggleFullScreen() @@ -102,16 +97,6 @@ class FileDownloadFragment : } } - override fun onStart() { - super.onStart() - listenForTransferProgress() - } - - override fun onStop() { - leaveTransferProgress() - super.onStop() - } - override fun onClick(v: View) { if (v.id == R.id.cancelBtn) { containerActivity.getFileOperationsHelper().cancelTransference(file) @@ -138,23 +123,6 @@ class FileDownloadFragment : } } - fun listenForTransferProgress() { - val listener = containerActivity.getFileDownloadProgressListener() ?: return - if (progressListener == null || listening) return - - listener.addDataTransferProgressListener(progressListener, file) - listening = true - setButtonsForTransferring(isTransferring = true) - } - - fun leaveTransferProgress() { - val listener = containerActivity.getFileDownloadProgressListener() ?: return - if (progressListener == null) return - - listener.removeDataTransferProgressListener(progressListener, file) - listening = false - } - fun setError(error: Boolean) { downloadError = error } diff --git a/app/src/main/res/layout/file_download_fragment.xml b/app/src/main/res/layout/file_download_fragment.xml index 7ecfa841bc8e..36533b2ab046 100644 --- a/app/src/main/res/layout/file_download_fragment.xml +++ b/app/src/main/res/layout/file_download_fragment.xml @@ -20,13 +20,13 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical" - android:padding="@dimen/card_corner_radius"> + android:padding="@dimen/standard_padding"> @@ -69,7 +69,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/standard_margin" - android:indeterminate="false" + android:indeterminate="true" app:indicatorColor="?attr/colorPrimary" app:trackColor="?attr/colorSurfaceContainerHighest" /> diff --git a/app/src/main/res/values/dims.xml b/app/src/main/res/values/dims.xml index 4c1368eae716..1249290b3f74 100644 --- a/app/src/main/res/values/dims.xml +++ b/app/src/main/res/values/dims.xml @@ -26,7 +26,7 @@ 512 28dp 16dp - 16dp + 12dp 32dp 64dp 8dp