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.java deleted file mode 100644 index 5223a8520ed1..000000000000 --- a/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2023 Alper Ozturk - * SPDX-FileCopyrightText: 2022 Álvaro Brey - * SPDX-FileCopyrightText: 2022 Tobias Kaminsky - * SPDX-FileCopyrightText: 2020 Chris Narkiewicz - * SPDX-FileCopyrightText: 2018 Andy Scherzinger - * SPDX-FileCopyrightText: 2015 ownCloud Inc. - * 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; - } - - 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); - - 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; - } - } - - 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); - - (mView.findViewById(R.id.cancelBtn)).setOnClickListener(this); - - (mView.findViewById(R.id.fileDownloadLL)).setOnClickListener(v -> { - if (getActivity() instanceof PreviewImageActivity previewImageActivity) { - previewImageActivity.toggleFullScreen(); - } - }); - - if (mError) { - setButtonsForRemote(); - } - else { - setButtonsForTransferring(); - } - - return mView; - } - - @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); - } - - @Override - public void onStart() { - super.onStart(); - listenForTransferProgress(); - } - - @Override - public void onStop() { - leaveTransferProgress(); - super.onStop(); - } - - @Override - public View getView() { - if (!mListening) { - listenForTransferProgress(); - } - return super.getView() == null ? mView : super.getView(); - } - - - @Override - public void onClick(View v) { - if (v.getId() == R.id.cancelBtn) { - containerActivity.getFileOperationsHelper().cancelTransference(getFile()); - requireActivity().finish(); - } else { - Log_OC.e(TAG, "Incorrect view clicked!"); - } - } - - - /** - * Enables or disables buttons for a file being downloaded - */ - private void setButtonsForTransferring() { - if (getView() == null) { - return; - } - - getView().findViewById(R.id.cancelBtn).setVisibility(View.VISIBLE); - - // 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; - } - - 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); - - // shows the error icon and message - getView().findViewById(R.id.errorText).setVisibility(View.VISIBLE); - getView().findViewById(R.id.error_image).setVisibility(View.VISIBLE); - } - - - public void listenForTransferProgress() { - if (mProgressListener != null && !mListening && containerActivity.getFileDownloadProgressListener() != null) { - containerActivity.getFileDownloadProgressListener().addDataTransferProgressListener(mProgressListener, getFile()); - mListening = true; - setButtonsForTransferring(); - } - } - - - public void leaveTransferProgress() { - if (mProgressListener != null && containerActivity.getFileDownloadProgressListener() != null) { - containerActivity.getFileDownloadProgressListener() - .removeDataTransferProgressListener(mProgressListener, getFile()); - mListening = false; - } - } - - public void setError(boolean error) { - mError = error; - } -} 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 new file mode 100644 index 000000000000..6fd02e267043 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/preview/FileDownloadFragment.kt @@ -0,0 +1,148 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-FileCopyrightText: 2022 Álvaro Brey + * SPDX-FileCopyrightText: 2022 Tobias Kaminsky + * SPDX-FileCopyrightText: 2020 Chris Narkiewicz + * SPDX-FileCopyrightText: 2018 Andy Scherzinger + * SPDX-FileCopyrightText: 2015 ownCloud Inc. + * 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.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.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 + + 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) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + super.onCreateView(inflater, container, savedInstanceState) + + if (!ignoreFirstSavedState) { + downloadError = requireArguments().getBoolean(EXTRA_ERROR) + instance().downloadFile(user!!, file) + } else { + ignoreFirstSavedState = false + } + + _binding = FileDownloadFragmentBinding.inflate(inflater, container, false) + + viewThemeUtils.material.run { + colorProgressBar(binding.progressBar) + colorMaterialTextButton(binding.cancelBtn) + themeCardView(binding.progressCard) + themeCardView(binding.errorCard) + } + + binding.cancelBtn.setOnClickListener(this) + binding.fileDownloadLL.setOnClickListener { + getTypedActivity(PreviewImageActivity::class.java)?.toggleFullScreen() + } + + setButtonsForTransferring(isTransferring = !downloadError) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.run { + putParcelable(EXTRA_FILE, file) + putParcelable(EXTRA_USER, user) + putBoolean(EXTRA_ERROR, downloadError) + } + } + + 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!") + } + } + + private fun setButtonsForTransferring(isTransferring: Boolean) { + val binding = _binding ?: return + + val transferringVisibility = if (isTransferring) View.VISIBLE else View.GONE + val remoteVisibility = if (isTransferring) View.GONE else View.VISIBLE + + binding.run { + downloadingContainer.visibility = transferringVisibility + errorContainer.visibility = remoteVisibility + + progressText.apply { + setText(R.string.downloader_download_in_progress_ticker) + visibility = transferringVisibility + } + } + } + + fun setError(error: Boolean) { + downloadError = 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) + } + } + } +} diff --git a/app/src/main/res/layout/file_download_fragment.xml b/app/src/main/res/layout/file_download_fragment.xml index ee6b760aded4..36533b2ab046 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/card_corner_radius" + 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..1249290b3f74 100644 --- a/app/src/main/res/values/dims.xml +++ b/app/src/main/res/values/dims.xml @@ -26,7 +26,9 @@ 512 28dp 16dp + 12dp 32dp + 64dp 8dp 4dp 32dp