From efdeedf132c7edc391167a42d257e3f9f3f9292f Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 9 Oct 2026 16:02:48 +0200 Subject: [PATCH 1/4] introduce repository pattern Signed-off-by: alperozturk96 --- .../java/com/nextcloud/client/di/AppModule.kt | 17 ++++ .../ui/activity/FileDisplayActivity.kt | 61 +++---------- .../FileDisplayActivityRepository.kt | 23 +++++ .../FileDisplayActivityRepositoryImpl.kt | 86 +++++++++++++++++++ .../FileDisplayActivityViewModel.kt | 26 +++++- 5 files changed, 165 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt create mode 100644 app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt diff --git a/app/src/main/java/com/nextcloud/client/di/AppModule.kt b/app/src/main/java/com/nextcloud/client/di/AppModule.kt index 7b5370afeae2..e4c63546154a 100644 --- a/app/src/main/java/com/nextcloud/client/di/AppModule.kt +++ b/app/src/main/java/com/nextcloud/client/di/AppModule.kt @@ -16,6 +16,7 @@ import android.content.pm.PackageManager import android.content.res.Resources import android.media.AudioManager import android.os.Handler +import androidx.lifecycle.ProcessLifecycleOwner import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.nextcloud.client.account.CurrentAccountProvider import com.nextcloud.client.account.UserAccountManager @@ -27,6 +28,7 @@ import com.nextcloud.client.core.ClockImpl import com.nextcloud.client.core.ThreadPoolAsyncRunner import com.nextcloud.client.database.dao.ArbitraryDataDao import com.nextcloud.client.device.DeviceInfo +import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.client.jobs.operation.FileOperationHelper import com.nextcloud.client.logger.FileLogHandler import com.nextcloud.client.logger.Logger @@ -54,6 +56,8 @@ import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.providers.UsersAndGroupsSearchConfig +import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepository +import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepositoryImpl import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl @@ -129,6 +133,19 @@ internal class AppModule { context: Context ): FileDataStorageManager = FileDataStorageManager(currentAccountProvider.user, context.contentResolver) + @Provides + fun clientRepository(currentAccountProvider: CurrentAccountProvider, context: Context): ClientRepository = + RemoteClientRepository(currentAccountProvider.user, context, ProcessLifecycleOwner.get()) + + @Provides + fun fileDisplayActivityRepository( + context: Context, + clientRepository: ClientRepository, + storageManager: FileDataStorageManager, + backgroundJobManager: BackgroundJobManager + ): FileDisplayActivityRepository = + FileDisplayActivityRepositoryImpl(context, clientRepository, storageManager, backgroundJobManager) + @Provides fun currentAccountProvider(accountManager: UserAccountManager): CurrentAccountProvider = accountManager 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 8fc39287dd64..580893deff3e 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 @@ -68,18 +68,15 @@ import com.nextcloud.client.di.ViewModelFactory import com.nextcloud.client.editimage.EditImageActivity import com.nextcloud.client.files.DeepLinkHandler import com.nextcloud.client.jobs.download.FileDownloadEventBroadcaster -import com.nextcloud.client.jobs.download.FileDownloadHelper import com.nextcloud.client.jobs.download.FileDownloadWorker import com.nextcloud.client.jobs.folderDownload.FolderDownloadEventBroadcaster import com.nextcloud.client.jobs.upload.FileUploadEventBroadcaster -import com.nextcloud.client.jobs.upload.FileUploadHelper import com.nextcloud.client.jobs.upload.FileUploadWorker import com.nextcloud.client.network.ClientFactory.CreationException import com.nextcloud.client.player.model.file.toPlaybackCollection import com.nextcloud.client.player.ui.audio.AudioPlayerLauncher import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.client.utils.IntentUtil -import com.nextcloud.model.OCUploadLocalPathData import com.nextcloud.ui.composeActivity.ComposeProcessTextAlias import com.nextcloud.utils.SnackbarUtil import com.nextcloud.utils.extensions.getParcelableArgument @@ -112,7 +109,6 @@ import com.owncloud.android.lib.resources.files.SearchRemoteOperation import com.owncloud.android.lib.resources.notifications.GetNotificationsRemoteOperation import com.owncloud.android.operations.CopyFileOperation import com.owncloud.android.operations.CreateFolderOperation -import com.owncloud.android.operations.DownloadType import com.owncloud.android.operations.FolderRefreshScheduler import com.owncloud.android.operations.MoveFileOperation import com.owncloud.android.operations.RefreshFolderOperation @@ -1177,15 +1173,7 @@ class FileDisplayActivity : return@isNetworkAndServerAvailable } - val data = OCUploadLocalPathData.forFile( - user.orElseThrow(Supplier { RuntimeException() }), - filePaths, - decryptedRemotePaths, - behaviour, - createRemoteFolder = true - ) - - FileUploadHelper.instance().uploadNewFiles(data) + viewModel.uploadFiles(filePaths, decryptedRemotePaths, behaviour) } } else { lifecycleScope.launch(Dispatchers.IO) { @@ -2599,9 +2587,8 @@ class FileDisplayActivity : } private fun requestForDownload() { - val user = user.orElseThrow(Supplier { RuntimeException() }) mWaitingToPreview?.let { - FileDownloadHelper.instance().downloadFileIfNotStartedBefore(user, it) + viewModel.downloadFileIfNotStartedBefore(it) } } @@ -2661,27 +2648,18 @@ class FileDisplayActivity : private fun executeSyncFolderOperation(folder: OCFile?, ignoreETag: Boolean) { val folder = folder ?: return - user.ifPresent { user -> - syncState = EmptyListState.LOADING + if (user.isEmpty) { + return + } - RefreshFolderOperation( - folder, - System.currentTimeMillis(), - false, - ignoreETag, - storageManager, - user, - applicationContext - ).execute( - account, - this, - { _, _ -> onSyncFinished() }, - handler, - null - ) + syncState = EmptyListState.LOADING - fetchRecommendedFilesIfNeeded(ignoreETag, folder) + lifecycleScope.launch { + viewModel.syncFolder(folder, ignoreETag) + onSyncFinished() } + + fetchRecommendedFilesIfNeeded(ignoreETag, folder) } private fun fetchRecommendedFilesIfNeeded(ignoreETag: Boolean, folder: OCFile?) { @@ -2707,18 +2685,7 @@ class FileDisplayActivity : } private fun requestForDownload(file: OCFile, downloadBehaviour: String, packageName: String, activityName: String) { - val currentUser = user.orElseThrow(Supplier { RuntimeException() }) - if (!FileDownloadHelper.instance().isDownloading(currentUser, file)) { - FileDownloadHelper.instance().downloadFile( - currentUser, - file, - downloadBehaviour, - DownloadType.DOWNLOAD, - activityName, - packageName, - null - ) - } + viewModel.downloadFile(file, downloadBehaviour, packageName, activityName) } private fun sendDownloadedFile(packageName: String, activityName: String) { @@ -3344,12 +3311,12 @@ class FileDisplayActivity : // region MetadataSyncJob private fun startMetadataSyncForRoot() { - backgroundJobManager.startMetadataSyncJob(OCFile.ROOT_PATH, folderAlreadySynced = true) + viewModel.startMetadataSync(OCFile.ROOT_PATH, folderAlreadySynced = true) } private fun startMetadataSyncForCurrentDir() { val currentDirId = file?.decryptedRemotePath ?: return - backgroundJobManager.startMetadataSyncJob(currentDirId) + viewModel.startMetadataSync(currentDirId, folderAlreadySynced = false) } // endregion diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt new file mode 100644 index 000000000000..ef8922b07ea5 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt @@ -0,0 +1,23 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.activity.filedisplayactivity + +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.operations.RemoteOperationResult + +interface FileDisplayActivityRepository { + suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> + + fun downloadFileIfNotStartedBefore(file: OCFile) + + fun downloadFile(file: OCFile, downloadBehaviour: String, packageName: String, activityName: String) + + fun uploadFiles(localPaths: Array, remotePaths: Array, localBehaviour: Int) + + fun startMetadataSync(remotePath: String, folderAlreadySynced: Boolean) +} diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt new file mode 100644 index 000000000000..07d4554732b3 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt @@ -0,0 +1,86 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.activity.filedisplayactivity + +import android.content.Context +import com.nextcloud.client.jobs.BackgroundJobManager +import com.nextcloud.client.jobs.download.FileDownloadHelper +import com.nextcloud.client.jobs.upload.FileUploadHelper +import com.nextcloud.model.OCUploadLocalPathData +import com.nextcloud.repository.ClientRepository +import com.owncloud.android.datamodel.FileDataStorageManager +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.operations.DownloadType +import com.owncloud.android.operations.RefreshFolderOperation +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class FileDisplayActivityRepositoryImpl( + private val context: Context, + private val clientRepository: ClientRepository, + private val storageManager: FileDataStorageManager, + private val backgroundJobManager: BackgroundJobManager +) : FileDisplayActivityRepository { + + private val user + get() = storageManager.user + + override suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> { + val client = clientRepository.getOwncloudClient() + ?: return RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) + + return withContext(Dispatchers.IO) { + RefreshFolderOperation( + folder, + System.currentTimeMillis(), + false, + ignoreETag, + storageManager, + user, + context + ).execute(client) + } + } + + override fun downloadFileIfNotStartedBefore(file: OCFile) { + FileDownloadHelper.instance().downloadFileIfNotStartedBefore(user, file) + } + + override fun downloadFile(file: OCFile, downloadBehaviour: String, packageName: String, activityName: String) { + val downloadHelper = FileDownloadHelper.instance() + if (downloadHelper.isDownloading(user, file)) { + return + } + + downloadHelper.downloadFile( + user, + file, + downloadBehaviour, + DownloadType.DOWNLOAD, + activityName, + packageName, + null + ) + } + + override fun uploadFiles(localPaths: Array, remotePaths: Array, localBehaviour: Int) { + val data = OCUploadLocalPathData.forFile( + user, + localPaths, + remotePaths, + localBehaviour, + createRemoteFolder = true + ) + FileUploadHelper.instance().uploadNewFiles(data) + } + + override fun startMetadataSync(remotePath: String, folderAlreadySynced: Boolean) { + backgroundJobManager.startMetadataSyncJob(remotePath, folderAlreadySynced) + } +} diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt index 477ab6e4f0e0..d91c15bd8fe2 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt @@ -12,9 +12,14 @@ import androidx.work.WorkInfo import androidx.work.WorkManager import com.nextcloud.client.jobs.BackgroundJobManagerImpl import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker +import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.common.operations.RemoteOperationResult import javax.inject.Inject -class FileDisplayActivityViewModel @Inject constructor(private val workManager: WorkManager) : ViewModel() { +class FileDisplayActivityViewModel @Inject constructor( + private val workManager: WorkManager, + private val repository: FileDisplayActivityRepository +) : ViewModel() { suspend fun observeOfflineWorker(onComplete: () -> Unit) { workManager @@ -25,4 +30,23 @@ class FileDisplayActivityViewModel @Inject constructor(private val workManager: } } } + + suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> = + repository.syncFolder(folder, ignoreETag) + + fun downloadFileIfNotStartedBefore(file: OCFile) { + repository.downloadFileIfNotStartedBefore(file) + } + + fun downloadFile(file: OCFile, downloadBehaviour: String, packageName: String, activityName: String) { + repository.downloadFile(file, downloadBehaviour, packageName, activityName) + } + + fun uploadFiles(localPaths: Array, remotePaths: Array, localBehaviour: Int) { + repository.uploadFiles(localPaths, remotePaths, localBehaviour) + } + + fun startMetadataSync(remotePath: String, folderAlreadySynced: Boolean) { + repository.startMetadataSync(remotePath, folderAlreadySynced) + } } From 714236427527536ebf0eefcb527832538abe66fe Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 9 Oct 2026 16:19:00 +0200 Subject: [PATCH 2/4] move recommended files fetch as well Signed-off-by: alperozturk96 --- .../java/com/nextcloud/client/di/AppModule.kt | 10 +++++++-- .../ui/activity/FileDisplayActivity.kt | 21 +++---------------- .../FileDisplayActivityRepository.kt | 2 ++ .../FileDisplayActivityRepositoryImpl.kt | 18 +++++++++++++++- .../FileDisplayActivityViewModel.kt | 3 +++ 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/di/AppModule.kt b/app/src/main/java/com/nextcloud/client/di/AppModule.kt index e4c63546154a..7216e363d0fc 100644 --- a/app/src/main/java/com/nextcloud/client/di/AppModule.kt +++ b/app/src/main/java/com/nextcloud/client/di/AppModule.kt @@ -58,6 +58,7 @@ import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.providers.UsersAndGroupsSearchConfig import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepository import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepositoryImpl +import com.owncloud.android.ui.fragment.filesRepository.RemoteFilesRepository as OCFileListFilesRepository import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl @@ -143,8 +144,13 @@ internal class AppModule { clientRepository: ClientRepository, storageManager: FileDataStorageManager, backgroundJobManager: BackgroundJobManager - ): FileDisplayActivityRepository = - FileDisplayActivityRepositoryImpl(context, clientRepository, storageManager, backgroundJobManager) + ): FileDisplayActivityRepository = FileDisplayActivityRepositoryImpl( + context, + clientRepository, + OCFileListFilesRepository(clientRepository, ProcessLifecycleOwner.get()), + storageManager, + backgroundJobManager + ) @Provides fun currentAccountProvider(accountManager: UserAccountManager): CurrentAccountProvider = accountManager 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 580893deff3e..47c3b5a69589 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 @@ -2663,24 +2663,9 @@ class FileDisplayActivity : } private fun fetchRecommendedFilesIfNeeded(ignoreETag: Boolean, folder: OCFile?) { - val optionalCapabilities = capabilities - if (optionalCapabilities.isEmpty) { - return - } - - if (folder?.isRootDirectory == false || optionalCapabilities.get().recommendations.isFalse) { - return - } - - user.ifPresent { user -> - val accountName = user.accountName - val fragment = this.listOfFilesFragment - lifecycleScope.launch(Dispatchers.IO) { - val recommendedFiles = filesRepository.fetchRecommendedFiles(accountName, ignoreETag, storageManager) - withContext(Dispatchers.Main) { - fragment?.adapter?.updateRecommendedFiles(recommendedFiles) - } - } + lifecycleScope.launch { + val files = viewModel.fetchRecommendedFiles(ignoreETag, folder) ?: return@launch + listOfFilesFragment?.adapter?.updateRecommendedFiles(files) } } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt index ef8922b07ea5..7f81dc5701cc 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepository.kt @@ -11,6 +11,8 @@ import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.operations.RemoteOperationResult interface FileDisplayActivityRepository { + suspend fun fetchRecommendedFiles(ignoreETag: Boolean, folder: OCFile?): ArrayList? + suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> fun downloadFileIfNotStartedBefore(file: OCFile) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt index 07d4554732b3..2b09983dc50f 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityRepositoryImpl.kt @@ -18,12 +18,15 @@ import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.operations.DownloadType import com.owncloud.android.operations.RefreshFolderOperation +import com.owncloud.android.ui.fragment.filesRepository.FilesRepository +import com.owncloud.android.utils.theme.CapabilityUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class FileDisplayActivityRepositoryImpl( private val context: Context, private val clientRepository: ClientRepository, + private val filesRepository: FilesRepository, private val storageManager: FileDataStorageManager, private val backgroundJobManager: BackgroundJobManager ) : FileDisplayActivityRepository { @@ -31,9 +34,22 @@ class FileDisplayActivityRepositoryImpl( private val user get() = storageManager.user + private val capabilities + get() = CapabilityUtils.getCapability(user, context) + + override suspend fun fetchRecommendedFiles(ignoreETag: Boolean, folder: OCFile?): ArrayList? { + if (folder?.isRootDirectory == false || capabilities.recommendations.isFalse) { + return null + } + + return filesRepository.fetchRecommendedFiles(user.accountName, ignoreETag, storageManager) + } + override suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> { val client = clientRepository.getOwncloudClient() - ?: return RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR) + ?: return RemoteOperationResult( + RemoteOperationResult.ResultCode.UNKNOWN_ERROR + ) return withContext(Dispatchers.IO) { RefreshFolderOperation( diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt index d91c15bd8fe2..f4cbb57ba368 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt @@ -34,6 +34,9 @@ class FileDisplayActivityViewModel @Inject constructor( suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> = repository.syncFolder(folder, ignoreETag) + suspend fun fetchRecommendedFiles(ignoreETag: Boolean, folder: OCFile?): ArrayList? = + repository.fetchRecommendedFiles(ignoreETag, folder) + fun downloadFileIfNotStartedBefore(file: OCFile) { repository.downloadFileIfNotStartedBefore(file) } From 58aa0a388a9db2624d2a9be2c2470eeff921009e Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 9 Oct 2026 16:26:51 +0200 Subject: [PATCH 3/4] observe view model Signed-off-by: alperozturk96 --- .../ui/activity/FileDisplayActivity.kt | 38 +++++++++++-------- .../FileDisplayActivityViewModel.kt | 26 +++++++++++-- 2 files changed, 44 insertions(+), 20 deletions(-) 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 47c3b5a69589..4b43f1f2deba 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 @@ -51,7 +51,9 @@ import androidx.core.view.MenuItemCompat import androidx.core.view.ViewCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.android.material.appbar.AppBarLayout import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -325,7 +327,7 @@ class FileDisplayActivity : } checkStoragePath() - observeWorkerState() + observeViewModel() handleBackPress() setupDrawer(menuItemId) } @@ -2093,12 +2095,26 @@ class FileDisplayActivity : override fun isDrawerIndicatorAvailable(): Boolean = isRoot(getCurrentDir()) - private fun observeWorkerState() { + private fun observeViewModel() { lifecycleScope.launch { viewModel.observeOfflineWorker(onComplete = { refreshCurrentDirectory() }) } + + lifecycleScope.launch { + viewModel.syncFolderResult.collect { + onSyncFinished() + } + } + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.recommendedFiles.collect { files -> + listOfFilesFragment?.adapter?.updateRecommendedFiles(files) + } + } + } } fun canPreviewInMediaPager(file: OCFile?): Boolean = @@ -2319,7 +2335,7 @@ class FileDisplayActivity : } supportInvalidateOptionsMenu() - fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) + viewModel.fetchRecommendedFiles(ignoreETag = true, currentDir) } override fun onAutoUploadFolderRemoved( @@ -2491,7 +2507,7 @@ class FileDisplayActivity : } refreshGalleryFragmentIfNeeded() - fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) + viewModel.fetchRecommendedFiles(ignoreETag = true, currentDir) } private fun onRenameFileOperationFinishForFileFragment(fragment: FileFragment, ocFile: OCFile, user: User) { @@ -2654,19 +2670,9 @@ class FileDisplayActivity : syncState = EmptyListState.LOADING - lifecycleScope.launch { - viewModel.syncFolder(folder, ignoreETag) - onSyncFinished() - } - - fetchRecommendedFilesIfNeeded(ignoreETag, folder) - } + viewModel.syncFolder(folder, ignoreETag) - private fun fetchRecommendedFilesIfNeeded(ignoreETag: Boolean, folder: OCFile?) { - lifecycleScope.launch { - val files = viewModel.fetchRecommendedFiles(ignoreETag, folder) ?: return@launch - listOfFilesFragment?.adapter?.updateRecommendedFiles(files) - } + viewModel.fetchRecommendedFiles(ignoreETag, folder) } private fun requestForDownload(file: OCFile, downloadBehaviour: String, packageName: String, activityName: String) { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt index f4cbb57ba368..8f8f61b4bf55 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/filedisplayactivity/FileDisplayActivityViewModel.kt @@ -8,12 +8,17 @@ package com.owncloud.android.ui.activity.filedisplayactivity import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import androidx.work.WorkInfo import androidx.work.WorkManager import com.nextcloud.client.jobs.BackgroundJobManagerImpl import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.operations.RemoteOperationResult +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.launch import javax.inject.Inject class FileDisplayActivityViewModel @Inject constructor( @@ -21,6 +26,12 @@ class FileDisplayActivityViewModel @Inject constructor( private val repository: FileDisplayActivityRepository ) : ViewModel() { + private val _recommendedFiles = MutableSharedFlow>(replay = 1) + val recommendedFiles: SharedFlow> = _recommendedFiles.asSharedFlow() + + private val _syncFolderResult = MutableSharedFlow>() + val syncFolderResult: SharedFlow> = _syncFolderResult.asSharedFlow() + suspend fun observeOfflineWorker(onComplete: () -> Unit) { workManager .getWorkInfosByTagFlow(BackgroundJobManagerImpl.formatClassTag(OfflineOperationsWorker::class)) @@ -31,11 +42,18 @@ class FileDisplayActivityViewModel @Inject constructor( } } - suspend fun syncFolder(folder: OCFile, ignoreETag: Boolean): RemoteOperationResult<*> = - repository.syncFolder(folder, ignoreETag) + fun syncFolder(folder: OCFile, ignoreETag: Boolean) { + viewModelScope.launch { + _syncFolderResult.emit(repository.syncFolder(folder, ignoreETag)) + } + } - suspend fun fetchRecommendedFiles(ignoreETag: Boolean, folder: OCFile?): ArrayList? = - repository.fetchRecommendedFiles(ignoreETag, folder) + fun fetchRecommendedFiles(ignoreETag: Boolean, folder: OCFile?) { + viewModelScope.launch { + val files = repository.fetchRecommendedFiles(ignoreETag, folder) ?: return@launch + _recommendedFiles.emit(files) + } + } fun downloadFileIfNotStartedBefore(file: OCFile) { repository.downloadFileIfNotStartedBefore(file) From 197624c3d867ce4e11bf56697e60596753c4c919 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 12 Oct 2026 12:08:03 +0200 Subject: [PATCH 4/4] fix build Signed-off-by: alperozturk96 --- app/src/main/java/com/nextcloud/client/di/AppModule.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/di/AppModule.kt b/app/src/main/java/com/nextcloud/client/di/AppModule.kt index 7216e363d0fc..06fa0254f84d 100644 --- a/app/src/main/java/com/nextcloud/client/di/AppModule.kt +++ b/app/src/main/java/com/nextcloud/client/di/AppModule.kt @@ -56,9 +56,6 @@ import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.providers.UsersAndGroupsSearchConfig -import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepository -import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepositoryImpl -import com.owncloud.android.ui.fragment.filesRepository.RemoteFilesRepository as OCFileListFilesRepository import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl @@ -66,6 +63,8 @@ import com.owncloud.android.ui.activities.data.activities.RemoteActivitiesReposi import com.owncloud.android.ui.activities.data.files.FilesRepository import com.owncloud.android.ui.activities.data.files.FilesServiceApiImpl import com.owncloud.android.ui.activities.data.files.RemoteFilesRepository +import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepository +import com.owncloud.android.ui.activity.filedisplayactivity.FileDisplayActivityRepositoryImpl import com.owncloud.android.ui.dialog.setupEncryption.CertificateValidator import com.owncloud.android.utils.theme.ViewThemeUtils import dagger.Module @@ -75,6 +74,7 @@ import java.io.File import javax.inject.Named import javax.inject.Provider import javax.inject.Singleton +import com.owncloud.android.ui.fragment.filesRepository.RemoteFilesRepository as OCFileListFilesRepository @Module(includes = [ComponentsModule::class, VariantComponentsModule::class, BuildTypeComponentsModule::class]) @Suppress("TooManyFunctions") @@ -134,10 +134,6 @@ internal class AppModule { context: Context ): FileDataStorageManager = FileDataStorageManager(currentAccountProvider.user, context.contentResolver) - @Provides - fun clientRepository(currentAccountProvider: CurrentAccountProvider, context: Context): ClientRepository = - RemoteClientRepository(currentAccountProvider.user, context, ProcessLifecycleOwner.get()) - @Provides fun fileDisplayActivityRepository( context: Context,