diff --git a/app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt b/app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt index 3356d69d0be5..7819c26fdc5c 100644 --- a/app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt +++ b/app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt @@ -93,7 +93,7 @@ interface FileDao { ORDER BY ${ProviderTableMeta.FILE_DEFAULT_SORT_ORDER} """ ) - fun getSubfiles( + suspend fun getSubfiles( parentId: Long, accountName: String, dirType: String = MimeType.DIRECTORY, diff --git a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt index e160e1dd4558..a15dda964192 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadWorker.kt @@ -22,7 +22,7 @@ import androidx.work.WorkerParameters import com.nextcloud.client.account.User import com.nextcloud.client.account.UserAccountManager import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerStateLiveData +import com.nextcloud.model.WorkerStateObserver import com.nextcloud.utils.ForegroundServiceHelper import com.nextcloud.utils.extensions.getPercent import com.owncloud.android.R @@ -152,11 +152,11 @@ class FileDownloadWorker( ) private fun setWorkerState(user: User?) { - WorkerStateLiveData.instance().setWorkState(WorkerState.DownloadStarted(user, currentDownload)) + WorkerStateObserver.send(WorkerState.FileDownloadStarted(user, currentDownload)) } private fun setIdleWorkerState() { - WorkerStateLiveData.instance().setWorkState(WorkerState.DownloadFinished(getCurrentFile())) + WorkerStateObserver.send(WorkerState.FileDownloadCompleted(getCurrentFile())) } private fun removePendingDownload(accountName: String?) { diff --git a/app/src/main/java/com/nextcloud/client/jobs/folderDownload/FolderDownloadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/folderDownload/FolderDownloadWorker.kt index 1ef24562c165..1f27c04f47e4 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/folderDownload/FolderDownloadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/folderDownload/FolderDownloadWorker.kt @@ -12,6 +12,8 @@ import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.jobs.download.FileDownloadHelper +import com.nextcloud.model.WorkerState +import com.nextcloud.model.WorkerStateObserver import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.OwnCloudClientManagerFactory @@ -132,6 +134,7 @@ class FolderDownloadWorker( Log_OC.d(TAG, "❌ failed reason: $e") Result.failure() } finally { + WorkerStateObserver.send(WorkerState.FolderDownloadCompleted(folder)) pendingDownloads.remove(folder.fileId) notificationManager?.dismiss() } diff --git a/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt index 9094918072e2..64b83867e827 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt @@ -17,7 +17,7 @@ import com.nextcloud.client.network.ClientFactoryImpl import com.nextcloud.client.network.ConnectivityService import com.nextcloud.model.OfflineOperationType import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerStateLiveData +import com.nextcloud.model.WorkerStateObserver import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.OwnCloudClient @@ -85,7 +85,7 @@ class OfflineOperationsWorker( processOperations(operations, client) // finish - WorkerStateLiveData.instance().setWorkState(WorkerState.OfflineOperationsCompleted) + WorkerStateObserver.send(WorkerState.OfflineOperationsCompleted) Log_OC.d(TAG, "🏁 Worker finished with result") return@withContext Result.success() } catch (e: Exception) { diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index 093a3a9b86ff..4db9981ed61e 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -22,7 +22,7 @@ import com.nextcloud.client.jobs.BackgroundJobManagerImpl import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerStateLiveData +import com.nextcloud.model.WorkerStateObserver import com.nextcloud.utils.ForegroundServiceHelper import com.nextcloud.utils.extensions.getPercent import com.nextcloud.utils.extensions.updateStatus @@ -180,11 +180,11 @@ class FileUploadWorker( } private fun setWorkerState(user: User?) { - WorkerStateLiveData.instance().setWorkState(WorkerState.UploadStarted(user)) + WorkerStateObserver.send(WorkerState.FileUploadStarted(user)) } private fun setIdleWorkerState() { - WorkerStateLiveData.instance().setWorkState(WorkerState.UploadFinished(currentUploadFileOperation?.file)) + WorkerStateObserver.send(WorkerState.FileUploadCompleted(currentUploadFileOperation?.file)) } @Suppress("ReturnCount", "LongMethod") diff --git a/app/src/main/java/com/nextcloud/model/WorkerState.kt b/app/src/main/java/com/nextcloud/model/WorkerState.kt index 6a1cca1330f0..7ed07584ac2d 100644 --- a/app/src/main/java/com/nextcloud/model/WorkerState.kt +++ b/app/src/main/java/com/nextcloud/model/WorkerState.kt @@ -12,9 +12,13 @@ import com.owncloud.android.datamodel.OCFile import com.owncloud.android.operations.DownloadFileOperation sealed class WorkerState { - data class DownloadFinished(var currentFile: OCFile?) : WorkerState() - data class DownloadStarted(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState() - data class UploadFinished(var currentFile: OCFile?) : WorkerState() - data class UploadStarted(var user: User?) : WorkerState() + data class FolderDownloadCompleted(var folder: OCFile) : WorkerState() + + data class FileDownloadStarted(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState() + data class FileDownloadCompleted(var currentFile: OCFile?) : WorkerState() + + data class FileUploadStarted(var user: User?) : WorkerState() + data class FileUploadCompleted(var currentFile: OCFile?) : WorkerState() + data object OfflineOperationsCompleted : WorkerState() } diff --git a/app/src/main/java/com/nextcloud/model/WorkerStateLiveData.kt b/app/src/main/java/com/nextcloud/model/WorkerStateLiveData.kt deleted file mode 100644 index 28d92b826752..000000000000 --- a/app/src/main/java/com/nextcloud/model/WorkerStateLiveData.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2023 Alper Ozturk - * SPDX-FileCopyrightText: 2023 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.nextcloud.model - -import androidx.lifecycle.LiveData - -class WorkerStateLiveData private constructor() : LiveData() { - - fun setWorkState(state: WorkerState) { - postValue(state) - } - - companion object { - private var instance: WorkerStateLiveData? = null - - fun instance(): WorkerStateLiveData = instance ?: synchronized(this) { - instance ?: WorkerStateLiveData().also { instance = it } - } - } -} diff --git a/app/src/main/java/com/nextcloud/model/WorkerStateObserver.kt b/app/src/main/java/com/nextcloud/model/WorkerStateObserver.kt new file mode 100644 index 000000000000..f8623f3b440c --- /dev/null +++ b/app/src/main/java/com/nextcloud/model/WorkerStateObserver.kt @@ -0,0 +1,22 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2023 Alper Ozturk + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH + * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only + */ +package com.nextcloud.model + +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow + +object WorkerStateObserver { + private const val BUFFER_CAPACITY = 25 + + private val _events = MutableSharedFlow(extraBufferCapacity = BUFFER_CAPACITY) + val events = _events.asSharedFlow() + + fun send(state: WorkerState) { + _events.tryEmit(state) + } +} diff --git a/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt index 19c96861e726..c02e4e9f95f7 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt @@ -9,8 +9,15 @@ package com.nextcloud.utils.extensions import android.app.Activity import android.content.Intent +import androidx.activity.ComponentActivity import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.nextcloud.model.WorkerState +import com.nextcloud.model.WorkerStateObserver +import kotlinx.coroutines.launch fun AppCompatActivity.isDialogFragmentReady(fragment: Fragment): Boolean = isActive() && !fragment.isStateSaved @@ -29,3 +36,13 @@ fun Activity.showShareIntent(text: String?) { val shareIntent = Intent.createChooser(sendIntent, null) startActivity(shareIntent) } + +fun ComponentActivity.observeWorker(onCollect: (WorkerState?) -> Unit) { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + WorkerStateObserver.events.collect { + onCollect(it) + } + } + } +} diff --git a/app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt index 2fec3fcc12d8..4a698dfa6398 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt @@ -31,7 +31,7 @@ fun FileDataStorageManager.getDecryptedPath(file: OCFile): String { .joinToString(OCFile.PATH_SEPARATOR) } -fun FileDataStorageManager.getSubfiles(id: Long, accountName: String): List = +suspend fun FileDataStorageManager.getSubfiles(id: Long, accountName: String): List = fileDao.getSubfiles(id, accountName).map { createFileInstance(it) } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 82dc1eaa77f4..c19927535692 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -46,7 +46,6 @@ import androidx.appcompat.widget.SearchView import androidx.core.view.MenuItemCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.android.material.appbar.AppBarLayout @@ -74,16 +73,16 @@ import com.nextcloud.client.utils.IntentUtil import com.nextcloud.model.ToolbarItem import com.nextcloud.model.ToolbarStyle import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerState.DownloadFinished -import com.nextcloud.model.WorkerState.DownloadStarted +import com.nextcloud.model.WorkerState.FileDownloadCompleted +import com.nextcloud.model.WorkerState.FileDownloadStarted import com.nextcloud.model.WorkerState.OfflineOperationsCompleted -import com.nextcloud.model.WorkerState.UploadFinished -import com.nextcloud.model.WorkerStateLiveData +import com.nextcloud.model.WorkerState.FileUploadCompleted import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.isActive import com.nextcloud.utils.extensions.lastFragment import com.nextcloud.utils.extensions.logFileSize import com.nextcloud.utils.extensions.navigateToAllFiles +import com.nextcloud.utils.extensions.observeWorker import com.nextcloud.utils.fileNameValidator.FileNameValidator.checkFolderPath import com.nextcloud.utils.view.FastScrollUtils import com.owncloud.android.MainApp @@ -1870,36 +1869,36 @@ class FileDisplayActivity : override fun isDrawerIndicatorAvailable(): Boolean = isRoot(getCurrentDir()) private fun observeWorkerState() { - WorkerStateLiveData.Companion.instance().observe( - this, - Observer { state: WorkerState? -> - when (state) { - is DownloadStarted -> { - Log_OC.d(TAG, "Download worker started") - handleDownloadWorkerState() - } + observeWorker { state -> + when (state) { + is FileDownloadStarted -> { + Log_OC.d(TAG, "Download worker started") + handleDownloadWorkerState() + } - is DownloadFinished -> { - fileDownloadProgressListener = null - previewFile(state) - } + is FileDownloadCompleted -> { + fileDownloadProgressListener = null + previewFile(state) + } - is UploadFinished -> { - refreshList() - } + is FileUploadCompleted -> { + refreshList() + } - is OfflineOperationsCompleted -> { - refreshCurrentDirectory() - } + is OfflineOperationsCompleted -> { + refreshCurrentDirectory() + } - else -> { - } + is WorkerState.FolderDownloadCompleted -> { + ocFileListFragment?.adapter?.notifyItemChanged(state.folder) } + + else -> Unit } - ) + } } - private fun previewFile(finishedState: DownloadFinished) { + private fun previewFile(finishedState: FileDownloadCompleted) { if (fileIDForImmediatePreview == -1L) { return } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt index ef3526ecdcfd..925928838a93 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.kt @@ -33,9 +33,9 @@ import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.jobs.download.FileDownloadHelper import com.nextcloud.client.onboarding.FirstRunActivity import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerState.DownloadStarted -import com.nextcloud.model.WorkerStateLiveData +import com.nextcloud.model.WorkerState.FileDownloadStarted import com.nextcloud.utils.extensions.getParcelableArgument +import com.nextcloud.utils.extensions.observeWorker import com.nextcloud.utils.mdm.MDMConfig.multiAccountSupport import com.owncloud.android.MainApp import com.owncloud.android.R @@ -454,10 +454,8 @@ class ManageAccountsActivity : } private fun observeWorkerState() { - WorkerStateLiveData.instance().observe( - this - ) { state: WorkerState? -> - if (state is DownloadStarted) { + observeWorker { state: WorkerState? -> + if (state is FileDownloadStarted) { Log_OC.d(TAG, "Download worker started") workerAccountName = state.user?.accountName workerCurrentDownload = state.currentDownload diff --git a/app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java index 7f6baa4d7dc1..054d6588c910 100755 --- a/app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java @@ -29,7 +29,7 @@ import com.nextcloud.client.jobs.upload.FileUploadWorker; import com.nextcloud.client.utils.Throttler; import com.nextcloud.model.WorkerState; -import com.nextcloud.model.WorkerStateLiveData; +import com.nextcloud.utils.extensions.ActivityExtensionsKt; import com.owncloud.android.R; import com.owncloud.android.databinding.UploadListLayoutBinding; import com.owncloud.android.datamodel.OCFile; @@ -50,6 +50,7 @@ import androidx.recyclerview.widget.GridLayoutManager; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import kotlin.Unit; /** * Activity listing pending, active, and completed uploads. User can delete completed uploads from view. Content of this @@ -130,11 +131,12 @@ protected void onCreate(Bundle savedInstanceState) { } private void observeWorkerState() { - WorkerStateLiveData.Companion.instance().observe(this, state -> { - if (state instanceof WorkerState.UploadStarted) { + ActivityExtensionsKt.observeWorker(this, state -> { + if (state instanceof WorkerState.FileUploadStarted) { Log_OC.d(TAG, "Upload worker started"); handleUploadWorkerState(); } + return Unit.INSTANCE; }); } diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt index 247641c500cd..5832e6fb04aa 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt @@ -45,6 +45,7 @@ import com.owncloud.android.utils.MimeTypeUtil import com.owncloud.android.utils.theme.ViewThemeUtils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -71,7 +72,7 @@ class OCFileListDelegate( var isMultiSelect = false private val asyncTasks: MutableList = ArrayList() private val asyncGalleryTasks: MutableList = ArrayList() - private val ioScope = CoroutineScope(Dispatchers.IO) + private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) fun setHighlightedItem(highlightedItem: OCFile?) { this.highlightedItem = highlightedItem @@ -253,11 +254,9 @@ class OCFileListDelegate( val isFolderPickerActivity = (context is FolderPickerActivity) gridViewHolder.checkbox.setVisibleIf(isMultiSelect && !isFolderPickerActivity) - // download state - gridViewHolder.localFileIndicator.visibility = View.GONE // default first - // metadata (downloaded, favorite) - bindGridMetadataViews(file, gridViewHolder) + showLocalFileIndicator(file, gridViewHolder) + gridViewHolder.favorite.setVisibleIf(file.isFavorite && showMetadata) // shares val shouldHideShare = ( @@ -351,29 +350,11 @@ class OCFileListDelegate( } } - private fun bindGridMetadataViews(file: OCFile, gridViewHolder: ListViewHolder) { - if (showMetadata) { - showLocalFileIndicator(file, gridViewHolder) - gridViewHolder.favorite.visibility = if (file.isFavorite) View.VISIBLE else View.GONE - } else { - gridViewHolder.localFileIndicator.visibility = View.GONE - gridViewHolder.favorite.visibility = View.GONE - } - } - - @Suppress("ReturnCount") - private fun isFolderFullyDownloaded(file: OCFile): Boolean { - if (!file.isFolder) { - return false - } - - val subfiles = storageManager.getSubfiles(file.fileId, user.accountName) - - if (subfiles.isEmpty()) { - return false - } - - return subfiles.all { it.isDown } + private suspend fun isFolderFullyDownloaded(file: OCFile): Boolean = withContext(Dispatchers.IO) { + file.isFolder && + storageManager.getSubfiles(file.fileId, user.accountName) + .takeIf { it.isNotEmpty() } + ?.all { it.isDown } == true } private fun isSynchronizing(file: OCFile): Boolean { @@ -386,36 +367,26 @@ class OCFileListDelegate( } private fun showLocalFileIndicator(file: OCFile, holder: ListViewHolder) { - val icon = when { - isSynchronizing(file) -> R.drawable.ic_synchronizing - file.etagInConflict != null -> R.drawable.ic_synchronizing_error - file.isDown -> R.drawable.ic_synced - else -> null - } - - holder.localFileIndicator.run { - if (icon != null) { - setImageResource(icon) - visibility = View.VISIBLE - } else { - visibility = View.GONE + ioScope.launch { + val isFullyDownloaded = isFolderFullyDownloaded(file) + val isSyncing = isSynchronizing(file) + val hasConflict = (file.etagInConflict != null) + val isDown = file.isDown + + val icon = when { + isSyncing -> R.drawable.ic_synchronizing + hasConflict -> R.drawable.ic_synchronizing_error + isDown || isFullyDownloaded -> R.drawable.ic_synced + else -> null } - } - - checkLocalFolderIndicatorAsynchronously(file, holder) - } - private fun checkLocalFolderIndicatorAsynchronously(file: OCFile, holder: ListViewHolder) { - if (file.isFolder) { - ioScope.launch { - if (isFolderFullyDownloaded(file)) { - withContext(Dispatchers.Main) { - holder.run { - if (thumbnail.tag == file.fileId) { - localFileIndicator.setImageResource(R.drawable.ic_synced) - localFileIndicator.visibility = View.VISIBLE - } - } + withContext(Dispatchers.Main) { + holder.localFileIndicator.run { + if (icon != null && showMetadata) { + setImageResource(icon) + visibility = View.VISIBLE + } else { + visibility = View.GONE } } } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java index 2aaa0b4f9139..e1990f7b652a 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -33,10 +33,10 @@ import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.model.WorkerState; -import com.nextcloud.model.WorkerStateLiveData; import com.nextcloud.ui.fileactions.FileAction; import com.nextcloud.ui.fileactions.FileActionsBottomSheet; import com.nextcloud.utils.MenuUtils; +import com.nextcloud.utils.extensions.ActivityExtensionsKt; import com.nextcloud.utils.extensions.BundleExtensionsKt; import com.nextcloud.utils.extensions.FileExtensionsKt; import com.nextcloud.utils.mdm.MDMConfig; @@ -84,6 +84,7 @@ import androidx.core.content.res.ResourcesCompat; import androidx.fragment.app.FragmentManager; import androidx.viewpager2.widget.ViewPager2; +import kotlin.Unit; /** * This Fragment is used to display the details about a file. @@ -541,7 +542,7 @@ public void updateFileDetails(OCFile file, User user) { * * @param transferring Flag signaling if the file should be considered as downloading or uploading, although * {@link FileDownloadHelper#isDownloading(User, OCFile)} and - * {@link FileUploadHelper#isUploading(User, OCFile)} return false. + * {@link FileUploadHelper#isUploading(String, String)} return false. * @param refresh If 'true', try to refresh the whole file from the database */ public void updateFileDetails(boolean transferring, boolean refresh) { @@ -625,12 +626,13 @@ public void onDownloadProgress(FileDownloadProgressEvent event) { } private void observeWorkerState() { - WorkerStateLiveData.Companion.instance().observe(getViewLifecycleOwner(), state -> { - if (state instanceof WorkerState.UploadStarted) { + ActivityExtensionsKt.observeWorker(requireActivity(), state -> { + if (state instanceof WorkerState.FileUploadStarted) { binding.progressText.setText(R.string.uploader_upload_in_progress_ticker); } else { binding.progressBlock.setVisibility(View.GONE); } + return Unit.INSTANCE; }); } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 2489b4d555d0..f8b9f81d1ce8 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -19,7 +19,6 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -1704,39 +1703,46 @@ public void switchToGridView() { @SuppressLint("NotifyDataSetChanged") public void switchLayoutManager(boolean grid) { + final var recyclerView = getRecyclerView(); + final var adapter = getAdapter(); + final var context = getContext(); + + if (context == null || adapter == null || recyclerView == null) { + Log_OC.e(TAG, "cannot switch layout, arguments are null"); + return; + } + int position = 0; - if (getRecyclerView() != null && getRecyclerView().getLayoutManager() != null) { - position = ((LinearLayoutManager) getRecyclerView().getLayoutManager()) - .findFirstCompletelyVisibleItemPosition(); + if (recyclerView.getLayoutManager() instanceof LinearLayoutManager linearLayoutManager) { + position = linearLayoutManager.findFirstCompletelyVisibleItemPosition(); } RecyclerView.LayoutManager layoutManager; if (grid) { - layoutManager = new GridLayoutManager(getContext(), getColumnsCount()); - ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + layoutManager = new GridLayoutManager(context, getColumnsCount()); + GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position == getAdapter().getItemCount() - 1 || position == 0 && getAdapter().shouldShowHeader()) { - return ((GridLayoutManager) layoutManager).getSpanCount(); + return gridLayoutManager.getSpanCount(); } else { return 1; } } }); - } else { - layoutManager = new LinearLayoutManager(getContext()); + layoutManager = new LinearLayoutManager(context); } - if (getRecyclerView() != null) { - getRecyclerView().setLayoutManager(layoutManager); - getRecyclerView().scrollToPosition(position); - getAdapter().setGridView(grid); - getRecyclerView().setAdapter(getAdapter()); - getAdapter().notifyDataSetChanged(); - } + recyclerView.setLayoutManager(layoutManager); + recyclerView.scrollToPosition(position); + adapter.setGridView(grid); + recyclerView.setAdapter(adapter); + adapter.notifyDataSetChanged(); + onRefresh(); } public CommonOCFileListAdapterInterface getCommonAdapter() { diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt index e45c42cd441f..f189c69a94ad 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt @@ -30,9 +30,9 @@ import com.nextcloud.client.jobs.download.FileDownloadWorker.Companion.getDownlo import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.getUploadFinishMessage import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.model.WorkerState -import com.nextcloud.model.WorkerStateLiveData import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSerializableArgument +import com.nextcloud.utils.extensions.observeWorker import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager @@ -325,9 +325,9 @@ class PreviewImageActivity : } private fun observeWorkerState() { - WorkerStateLiveData.instance().observe(this) { state: WorkerState? -> + observeWorker { state: WorkerState? -> when (state) { - is WorkerState.DownloadStarted -> { + is WorkerState.FileDownloadStarted -> { Log_OC.d(TAG, "Download worker started") isDownloadWorkStarted = true @@ -336,7 +336,7 @@ class PreviewImageActivity : } } - is WorkerState.DownloadFinished -> { + is WorkerState.FileDownloadCompleted -> { Log_OC.d(TAG, "Download worker stopped") isDownloadWorkStarted = false diff --git a/app/src/main/res/layout/grid_item.xml b/app/src/main/res/layout/grid_item.xml index ae065d33d73a..ddbbc8c627c3 100644 --- a/app/src/main/res/layout/grid_item.xml +++ b/app/src/main/res/layout/grid_item.xml @@ -124,6 +124,7 @@ android:layout_marginEnd="@dimen/grid_layout_margin_end" android:contentDescription="@string/synced_icon" android:src="@drawable/ic_synced" + android:visibility="gone" tools:visibility="visible" /> diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml index 619f42a3231e..a8ef241b52e8 100644 --- a/app/src/main/res/layout/list_item.xml +++ b/app/src/main/res/layout/list_item.xml @@ -48,6 +48,8 @@ android:layout_width="@dimen/list_item_local_file_indicator_layout_width" android:layout_height="@dimen/list_item_local_file_indicator_layout_height" android:contentDescription="@string/downloader_download_succeeded_ticker" + android:visibility="gone" + tools:visibility="visible" android:scaleType="fitCenter" android:src="@drawable/ic_synced" app:layout_constraintBottom_toBottomOf="@+id/thumbnail_container" diff --git a/app/src/main/res/layout/recommended_file_item.xml b/app/src/main/res/layout/recommended_file_item.xml index 738cf5900cc3..0d91762076a2 100644 --- a/app/src/main/res/layout/recommended_file_item.xml +++ b/app/src/main/res/layout/recommended_file_item.xml @@ -119,6 +119,7 @@ android:layout_width="@dimen/grid_layout_item_size" android:layout_height="@dimen/grid_layout_item_size" android:layout_marginEnd="@dimen/grid_layout_margin_end" + android:visibility="gone" android:contentDescription="@string/synced_icon" android:src="@drawable/ic_synced" tools:visibility="visible" />