Browse Source

Fix tracking current download status

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 year ago
parent
commit
742f01259d

+ 1 - 1
app/src/main/java/com/nextcloud/client/files/downloader/FileDownloadHelper.kt

@@ -63,7 +63,7 @@ class FileDownloadHelper {
         return backgroundJobManager.isStartFileDownloadJobScheduled(
             user,
             file
-        )
+        ) || FileDownloadWorker.isDownloading(user, file)
     }
 
     fun cancelPendingOrCurrentDownloads(user: User?, file: OCFile?) {

+ 15 - 10
app/src/main/java/com/nextcloud/client/files/downloader/FileDownloadWorker.kt

@@ -24,6 +24,7 @@ package com.nextcloud.client.files.downloader
 import android.accounts.Account
 import android.accounts.AccountManager
 import android.accounts.OnAccountsUpdateListener
+import android.annotation.SuppressLint
 import android.app.PendingIntent
 import android.content.Context
 import androidx.core.util.component1
@@ -34,8 +35,8 @@ import androidx.work.WorkerParameters
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.UserAccountManager
 import com.nextcloud.java.util.Optional
-import com.nextcloud.model.DownloadWorkerState
-import com.nextcloud.model.DownloadWorkerStateLiveData
+import com.nextcloud.model.WorkerState
+import com.nextcloud.model.WorkerStateLiveData
 import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.UploadsStorageManager
@@ -66,8 +67,10 @@ class FileDownloadWorker(
     companion object {
         private val TAG = FileDownloadWorker::class.java.simpleName
 
+        @SuppressLint("StaticFieldLeak")
+        private var currentDownload: DownloadFileOperation? = null
+
         const val FILES_SEPARATOR = ","
-        const val WORKER_TAG = "WORKER_TAG"
         const val FOLDER_PATH = "FOLDER_PATH"
         const val USER_NAME = "USER"
         const val FILE_PATH = "FILE_PATH"
@@ -84,6 +87,11 @@ class FileDownloadWorker(
         const val EXTRA_LINKED_TO_PATH = "LINKED_TO"
         const val ACCOUNT_NAME = "ACCOUNT_NAME"
 
+        fun isDownloading(user: User, file: OCFile): Boolean {
+            return currentDownload?.file?.fileId == file.fileId &&
+                currentDownload?.user?.accountName == user.accountName
+        }
+
         fun getDownloadAddedMessage(): String {
             return FileDownloadWorker::class.java.name + "DOWNLOAD_ADDED"
         }
@@ -93,7 +101,7 @@ class FileDownloadWorker(
         }
     }
 
-    private var currentDownload: DownloadFileOperation? = null
+    private val pendingDownloads = IndexedForest<DownloadFileOperation>()
     private var conflictUploadId: Long? = null
     private var lastPercent = 0
     private val intents = FileDownloadIntents(context)
@@ -106,8 +114,6 @@ class FileDownloadWorker(
     private var user: User? = null
     private var folder: OCFile? = null
     private var isAnyOperationFailed = true
-    private var workerTag: String? = null
-    private val pendingDownloads = IndexedForest<DownloadFileOperation>()
 
     @Suppress("TooGenericExceptionCaught")
     override fun doWork(): Result {
@@ -147,12 +153,11 @@ class FileDownloadWorker(
     }
 
     private fun setWorkerState(user: User?) {
-        val worker = DownloadWorkerState(workerTag ?: "", user, pendingDownloads)
-        DownloadWorkerStateLiveData.instance().addWorker(worker)
+        WorkerStateLiveData.instance().setWorkState(WorkerState.Download(user, currentDownload))
     }
 
     private fun setIdleWorkerState() {
-        DownloadWorkerStateLiveData.instance().removeWorker(workerTag ?: "")
+        WorkerStateLiveData.instance().setWorkState(WorkerState.Idle)
     }
 
     private fun notifyForFolderResult(folder: OCFile) {
@@ -165,7 +170,6 @@ class FileDownloadWorker(
         val files = getFiles()
         val downloadType = getDownloadType()
 
-        workerTag = inputData.keyValueMap[WORKER_TAG] as String? ?: ""
         conflictUploadId = inputData.keyValueMap[CONFLICT_UPLOAD_ID] as Long?
 
         val behaviour = inputData.keyValueMap[BEHAVIOUR] as String? ?: ""
@@ -216,6 +220,7 @@ class FileDownloadWorker(
             it.value.payload?.cancel()
         }
         pendingDownloads.all.clear()
+        currentDownload = null
     }
 
     private fun setUser() {

+ 0 - 3
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -34,7 +34,6 @@ import androidx.work.PeriodicWorkRequest
 import androidx.work.WorkInfo
 import androidx.work.WorkManager
 import androidx.work.workDataOf
-import com.google.gson.Gson
 import com.nextcloud.client.account.User
 import com.nextcloud.client.core.Clock
 import com.nextcloud.client.di.Injectable
@@ -42,7 +41,6 @@ import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork
 import com.nextcloud.client.files.downloader.FileDownloadWorker
 import com.nextcloud.client.preferences.AppPreferences
 import com.nextcloud.utils.extensions.isWorkScheduled
-import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.operations.DownloadType
 import java.util.Date
@@ -549,7 +547,6 @@ internal class BackgroundJobManagerImpl(
         val tag = startFileDownloadJobTag(user, file)
 
         val data = workDataOf(
-            FileDownloadWorker.WORKER_TAG to tag,
             FileDownloadWorker.USER_NAME to user.accountName,
             FileDownloadWorker.FILE_PATH to file.remotePath,
             FileDownloadWorker.BEHAVIOUR to behaviour,

+ 0 - 71
app/src/main/java/com/nextcloud/model/DownloadWorkerStateLiveData.kt

@@ -1,71 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Alper Ozturk
- * Copyright (C) 2023 Alper Ozturk
- * Copyright (C) 2023 Nextcloud GmbH
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.model
-
-import androidx.lifecycle.LiveData
-import com.nextcloud.client.account.User
-import com.owncloud.android.datamodel.OCFile
-
-class DownloadWorkerStateLiveData private constructor(): LiveData<ArrayList<DownloadWorkerState>>() {
-
-    private var workers: ArrayList<DownloadWorkerState> = arrayListOf()
-
-    fun isDownloading(user: User?, file: OCFile?): Boolean {
-        if (user == null || file == null) {
-            return false
-        }
-
-        var result = false
-
-        workers.forEach { downloadState ->
-            downloadState.pendingDownloads?.all?.forEach { download ->
-                result = download.value?.payload?.file?.fileId == file.fileId
-            }
-        }
-
-        return result
-    }
-
-    fun removeWorker(tag: String) {
-        workers.forEach {
-            if (it.tag == tag) {
-                workers.remove(it)
-            }
-        }
-        postValue(workers)
-    }
-
-    fun addWorker(state: DownloadWorkerState) {
-        workers.add(state)
-        postValue(workers)
-    }
-
-    companion object {
-        private var instance: DownloadWorkerStateLiveData? = null
-
-        fun instance(): DownloadWorkerStateLiveData {
-            return instance ?: synchronized(this) {
-                instance ?: DownloadWorkerStateLiveData().also { instance = it }
-            }
-        }
-    }
-}

+ 4 - 2
app/src/main/java/com/nextcloud/model/WorkerState.kt

@@ -22,7 +22,9 @@
 package com.nextcloud.model
 
 import com.nextcloud.client.account.User
-import com.owncloud.android.files.services.IndexedForest
 import com.owncloud.android.operations.DownloadFileOperation
 
-data class DownloadWorkerState(var tag: String, var user: User?, var pendingDownloads: IndexedForest<DownloadFileOperation>?)
+sealed class WorkerState {
+    object Idle : WorkerState()
+    class Download(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState()
+}

+ 41 - 0
app/src/main/java/com/nextcloud/model/WorkerStateLiveData.kt

@@ -0,0 +1,41 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alper Ozturk
+ * Copyright (C) 2023 Alper Ozturk
+ * Copyright (C) 2023 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.model
+
+import androidx.lifecycle.LiveData
+
+class WorkerStateLiveData private constructor() : LiveData<WorkerState>() {
+
+    fun setWorkState(state: WorkerState) {
+        postValue(state)
+    }
+
+    companion object {
+        private var instance: WorkerStateLiveData? = null
+
+        fun instance(): WorkerStateLiveData {
+            return instance ?: synchronized(this) {
+                instance ?: WorkerStateLiveData().also { instance = it }
+            }
+        }
+    }
+}

+ 4 - 3
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -73,7 +73,8 @@ import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.utils.IntentUtil;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.DownloadWorkerStateLiveData;
+import com.nextcloud.model.WorkerState;
+import com.nextcloud.model.WorkerStateLiveData;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.nextcloud.utils.view.FastScrollUtils;
@@ -1562,8 +1563,8 @@ public class FileDisplayActivity extends FileActivity
     }
 
     private void observeDownloadWorkerState() {
-        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (!state.isEmpty()) {
+        WorkerStateLiveData.Companion.instance().observe(this, state -> {
+            if (state instanceof WorkerState.Download) {
                 Log_OC.d(TAG, "Download worker started");
                 handleDownloadWorkerState();
             }

+ 16 - 25
app/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java

@@ -37,6 +37,7 @@ import android.os.Handler;
 import android.os.IBinder;
 import android.view.MenuItem;
 import android.view.View;
+
 import com.google.common.collect.Sets;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
@@ -44,8 +45,8 @@ import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.onboarding.FirstRunActivity;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.DownloadWorkerState;
-import com.nextcloud.model.DownloadWorkerStateLiveData;
+import com.nextcloud.model.WorkerState;
+import com.nextcloud.model.WorkerStateLiveData;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -54,7 +55,6 @@ import com.owncloud.android.datamodel.ArbitraryDataProvider;
 import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.files.services.IndexedForest;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.UserInfo;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -115,7 +115,8 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
     private ArbitraryDataProvider arbitraryDataProvider;
     private boolean multipleAccountsSupported;
 
-    private final ArrayList<DownloadWorkerState> downloadWorkerStates = new ArrayList<>();
+    private String workerAccountName;
+    private DownloadFileOperation workerCurrentDownload;
 
     @Inject BackgroundJobManager backgroundJobManager;
     @Inject UserAccountManager accountManager;
@@ -164,7 +165,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         recyclerView.setAdapter(userListAdapter);
         recyclerView.setLayoutManager(new LinearLayoutManager(this));
         initializeComponentGetters();
-        observeDownloadWorkerState();
+        observeWorkerState();
     }
 
 
@@ -341,7 +342,7 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
                     mUploaderBinder.cancel(accountName);
                 }
 
-                cancelAllDownloadsForAccount();
+                FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(workerAccountName, workerCurrentDownload);
             }
 
             User currentUser = getUserAccountManager().getUser();
@@ -409,20 +410,6 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         return new ManageAccountsServiceConnection();
     }
 
-    private void cancelAllDownloadsForAccount() {
-        for (DownloadWorkerState workerState : downloadWorkerStates) {
-            User currentUser =  workerState.getUser();
-            IndexedForest<DownloadFileOperation> pendingDownloads = workerState.getPendingDownloads();
-
-            if (currentUser != null && pendingDownloads != null) {
-                pendingDownloads.getAll().values().forEach((value) -> {
-                    DownloadFileOperation operation = value.getPayload();
-                    FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(currentUser.getAccountName(), operation);
-                });
-            }
-        }
-    }
-
     private void performAccountRemoval(User user) {
         // disable account in recycler view
         for (int i = 0; i < userListAdapter.getItemCount(); i++) {
@@ -445,7 +432,8 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
             mUploaderBinder.cancel(user);
         }
 
-        cancelAllDownloadsForAccount();
+        FileDownloadHelper.Companion.instance().cancelAllDownloadsForAccount(workerAccountName, workerCurrentDownload);
+
         backgroundJobManager.startAccountRemovalJob(user.getAccountName(), false);
 
         // immediately select a new account
@@ -529,10 +517,13 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
         }
     }
 
-    private void observeDownloadWorkerState() {
-        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
-            Log_OC.d(TAG, "Download worker started");
-            downloadWorkerStates.addAll(state);
+    private void observeWorkerState() {
+        WorkerStateLiveData.Companion.instance().observe(this, state -> {
+            if (state instanceof WorkerState.Download) {
+                Log_OC.d(TAG, "Download worker started");
+                workerAccountName = ((WorkerState.Download) state).getUser().getAccountName();
+                workerCurrentDownload = ((WorkerState.Download) state).getCurrentDownload();
+            }
         });
     }
 

+ 0 - 1
app/src/main/java/com/owncloud/android/ui/adapter/GalleryAdapter.kt

@@ -31,7 +31,6 @@ import android.os.Looper
 import android.view.LayoutInflater
 import android.view.ViewGroup
 import androidx.annotation.VisibleForTesting
-import androidx.lifecycle.LifecycleOwner
 import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter
 import com.afollestad.sectionedrecyclerview.SectionedViewHolder
 import com.nextcloud.client.account.User

+ 7 - 9
app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt

@@ -34,7 +34,6 @@ import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.client.account.User
 import com.nextcloud.client.files.downloader.FileDownloadHelper
 import com.nextcloud.client.preferences.AppPreferences
-import com.nextcloud.model.DownloadWorkerStateLiveData
 import com.nextcloud.utils.extensions.createRoundedOutline
 import com.owncloud.android.R
 import com.owncloud.android.datamodel.FileDataStorageManager
@@ -344,26 +343,25 @@ class OCFileListDelegate(
         val operationsServiceBinder = transferServiceGetter.operationsServiceBinder
         val fileUploaderBinder = transferServiceGetter.fileUploaderBinder
 
-        val isDownloading = if (file.isFolder) {
-            FileDownloadHelper.instance().isDownloading(user, file)
-        } else {
-            DownloadWorkerStateLiveData.instance().isDownloading(user, file)
-        }
-
         val icon: Int? = when {
             operationsServiceBinder?.isSynchronizing(user, file) == true ||
-                isDownloading ||
+                FileDownloadHelper.instance().isDownloading(user, file) ||
                 fileUploaderBinder?.isUploading(user, file) == true -> {
                 // synchronizing, downloading or uploading
                 R.drawable.ic_synchronizing
             }
+
             file.etagInConflict != null -> {
                 R.drawable.ic_synchronizing_error
             }
+
             file.isDown -> {
                 R.drawable.ic_synced
             }
-            else -> { null }
+
+            else -> {
+                null
+            }
         }
 
         gridViewHolder.localFileIndicator.run {

+ 4 - 3
app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java

@@ -41,7 +41,8 @@ import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.files.downloader.FileDownloadWorker;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.java.util.Optional;
-import com.nextcloud.model.DownloadWorkerStateLiveData;
+import com.nextcloud.model.WorkerState;
+import com.nextcloud.model.WorkerStateLiveData;
 import com.nextcloud.utils.extensions.IntentExtensionsKt;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -306,8 +307,8 @@ public class PreviewImageActivity extends FileActivity implements
     }
 
     private void observeDownloadWorkerState() {
-        DownloadWorkerStateLiveData.Companion.instance().observe(this, state -> {
-            if (!state.isEmpty()) {
+       WorkerStateLiveData.Companion.instance().observe(this, state -> {
+            if (state instanceof WorkerState.Download) {
                 Log_OC.d(TAG, "Download worker started");
                 isDownloadWorkStarted = true;