Browse Source

Rebase master

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

+ 12 - 14
app/src/main/java/com/owncloud/android/files/FileMenuFilter.java

@@ -31,12 +31,12 @@ import android.view.Menu;
 import com.nextcloud.android.files.FileLockingHelper;
 import com.nextcloud.android.files.FileLockingHelper;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.editimage.EditImageActivity;
 import com.nextcloud.client.editimage.EditImageActivity;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
+import com.nextcloud.client.jobs.download.FileDownloadHelper;
+import com.nextcloud.client.jobs.upload.FileUploadHelper;
 import com.nextcloud.utils.EditorUtils;
 import com.nextcloud.utils.EditorUtils;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.ui.activity.ComponentsGetter;
@@ -383,10 +383,9 @@ public class FileMenuFilter {
         boolean synchronizing = false;
         boolean synchronizing = false;
         if (componentsGetter != null && !files.isEmpty() && user != null) {
         if (componentsGetter != null && !files.isEmpty() && user != null) {
             OperationsServiceBinder opsBinder = componentsGetter.getOperationsServiceBinder();
             OperationsServiceBinder opsBinder = componentsGetter.getOperationsServiceBinder();
-            FileUploaderBinder uploaderBinder = componentsGetter.getFileUploaderBinder();
             synchronizing = anyFileSynchronizing(opsBinder) ||      // comparing local and remote
             synchronizing = anyFileSynchronizing(opsBinder) ||      // comparing local and remote
-                            anyFileDownloading() ||
-                            anyFileUploading(uploaderBinder);
+                anyFileDownloading() ||
+                anyFileUploading();
         }
         }
         return synchronizing;
         return synchronizing;
     }
     }
@@ -411,21 +410,20 @@ public class FileMenuFilter {
         return false;
         return false;
     }
     }
 
 
-    private boolean anyFileUploading(FileUploaderBinder uploaderBinder) {
-        boolean uploading = false;
-        if (uploaderBinder != null) {
-            for (Iterator<OCFile> iterator = files.iterator(); !uploading && iterator.hasNext(); ) {
-                uploading = uploaderBinder.isUploading(user, iterator.next());
+    private boolean anyFileUploading() {
+        for (OCFile file : files) {
+            if (FileUploadHelper.Companion.instance().isUploading(user, file)) {
+                return true;
             }
             }
         }
         }
-        return uploading;
+        return false;
     }
     }
 
 
     private boolean isShareApiEnabled(OCCapability capability) {
     private boolean isShareApiEnabled(OCCapability capability) {
         return capability != null &&
         return capability != null &&
-                (capability.getFilesSharingApiEnabled().isTrue() ||
-                        capability.getFilesSharingApiEnabled().isUnknown()
-                );
+            (capability.getFilesSharingApiEnabled().isTrue() ||
+                capability.getFilesSharingApiEnabled().isUnknown()
+            );
     }
     }
 
 
     private boolean isShareWithUsersAllowed() {
     private boolean isShareWithUsersAllowed() {

+ 1 - 1
app/src/main/java/com/owncloud/android/files/services/FileUploader.java

@@ -750,7 +750,7 @@ public class FileUploader extends Service
         }
         }
 
 
         public void clearListeners() {
         public void clearListeners() {
-            FilesUploadHelper.Progress.getMBoundListeners().clear();
+            FilesUploadHelper.Companion.getMBoundListeners().clear();
             mBoundListeners.clear();
             mBoundListeners.clear();
         }
         }
 
 

+ 1 - 41
app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java

@@ -25,13 +25,10 @@ package com.owncloud.android.ui.activity;
 
 
 import android.accounts.Account;
 import android.accounts.Account;
 import android.content.BroadcastReceiver;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.os.Bundle;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.view.Menu;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MenuItem;
@@ -181,6 +178,7 @@ public class UploadListActivity extends FileActivity {
         swipeListRefreshLayout.setOnRefreshListener(this::refresh);
         swipeListRefreshLayout.setOnRefreshListener(this::refresh);
 
 
         loadItems();
         loadItems();
+        uploadListAdapter.loadUploadItemsFromDb();
     }
     }
 
 
     private void loadItems() {
     private void loadItems() {
@@ -320,44 +318,6 @@ public class UploadListActivity extends FileActivity {
         }
         }
     }
     }
 
 
-
-    @Override
-    protected ServiceConnection newTransferenceServiceConnection() {
-        return new UploadListServiceConnection();
-    }
-
-    /**
-     * Defines callbacks for service binding, passed to bindService()
-     */
-    private class UploadListServiceConnection implements ServiceConnection {
-
-        @Override
-        public void onServiceConnected(ComponentName component, IBinder service) {
-            if (service instanceof FileUploaderBinder) {
-                if (mUploaderBinder == null) {
-                    mUploaderBinder = (FileUploaderBinder) service;
-                    Log_OC.d(TAG, "UploadListActivity connected to Upload service. component: " +
-                            component + " service: " + service);
-                    uploadListAdapter.loadUploadItemsFromDb();
-                } else {
-                    Log_OC.d(TAG, "mUploaderBinder already set. mUploaderBinder: " +
-                        mUploaderBinder + " service:" + service);
-                }
-            } else {
-                Log_OC.d(TAG, "UploadListActivity not connected to Upload service. component: " +
-                    component + " service: " + service);
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName component) {
-            if (component.equals(new ComponentName(UploadListActivity.this, FileUploader.class))) {
-                Log_OC.d(TAG, "UploadListActivity suddenly disconnected from Upload service");
-                mUploaderBinder = null;
-            }
-        }
-    }
-
     /**
     /**
      * Once the file upload has changed its status -> update uploads list view
      * Once the file upload has changed its status -> update uploads list view
      */
      */

+ 4 - 3
app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt

@@ -32,7 +32,8 @@ import androidx.core.content.res.ResourcesCompat
 import com.elyeproj.loaderviewlibrary.LoaderImageView
 import com.elyeproj.loaderviewlibrary.LoaderImageView
 import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User
-import com.nextcloud.client.files.downloader.FileDownloadHelper
+import com.nextcloud.client.jobs.download.FileDownloadHelper
+import com.nextcloud.client.jobs.upload.FileUploadHelper
 import com.nextcloud.client.preferences.AppPreferences
 import com.nextcloud.client.preferences.AppPreferences
 import com.nextcloud.utils.extensions.createRoundedOutline
 import com.nextcloud.utils.extensions.createRoundedOutline
 import com.owncloud.android.R
 import com.owncloud.android.R
@@ -53,6 +54,7 @@ import com.owncloud.android.utils.theme.ViewThemeUtils
 
 
 @Suppress("LongParameterList", "TooManyFunctions")
 @Suppress("LongParameterList", "TooManyFunctions")
 class OCFileListDelegate(
 class OCFileListDelegate(
+    private val fileUploadHelper: FileUploadHelper,
     private val context: Context,
     private val context: Context,
     private val ocFileListFragmentInterface: OCFileListFragmentInterface,
     private val ocFileListFragmentInterface: OCFileListFragmentInterface,
     private val user: User,
     private val user: User,
@@ -343,12 +345,11 @@ class OCFileListDelegate(
 
 
     private fun showLocalFileIndicator(file: OCFile, gridViewHolder: ListGridImageViewHolder) {
     private fun showLocalFileIndicator(file: OCFile, gridViewHolder: ListGridImageViewHolder) {
         val operationsServiceBinder = transferServiceGetter.operationsServiceBinder
         val operationsServiceBinder = transferServiceGetter.operationsServiceBinder
-        val fileUploaderBinder = transferServiceGetter.fileUploaderBinder
 
 
         val icon: Int? = when {
         val icon: Int? = when {
             operationsServiceBinder?.isSynchronizing(user, file) == true ||
             operationsServiceBinder?.isSynchronizing(user, file) == true ||
                 FileDownloadHelper.instance().isDownloading(user, file) ||
                 FileDownloadHelper.instance().isDownloading(user, file) ||
-                fileUploaderBinder?.isUploading(user, file) == true -> {
+                fileUploadHelper.isUploading(user, file) -> {
                 // synchronizing, downloading or uploading
                 // synchronizing, downloading or uploading
                 R.drawable.ic_synchronizing
                 R.drawable.ic_synchronizing
             }
             }

+ 24 - 14
app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -44,8 +44,9 @@ import com.google.android.material.tabs.TabLayout;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.jobs.BackgroundJobManager;
+import com.nextcloud.client.jobs.download.FileDownloadHelper;
+import com.nextcloud.client.jobs.upload.FileUploadHelper;
 import com.nextcloud.client.network.ClientFactory;
 import com.nextcloud.client.network.ClientFactory;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.preferences.AppPreferences;
@@ -58,7 +59,6 @@ import com.owncloud.android.databinding.FileDetailsFragmentBinding;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
-import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@@ -233,7 +233,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         } else {
         } else {
             binding.emptyList.emptyListView.setVisibility(View.GONE);
             binding.emptyList.emptyListView.setVisibility(View.GONE);
         }
         }
-        
+
         Context context = getContext();
         Context context = getContext();
         if (context == null) {
         if (context == null) {
             return null;
             return null;
@@ -506,7 +506,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      *
      *
      * @param transferring Flag signaling if the file should be considered as downloading or uploading, although
      * @param transferring Flag signaling if the file should be considered as downloading or uploading, although
      *                     {@link FileDownloadHelper#isDownloading(User, OCFile)}  and
      *                     {@link FileDownloadHelper#isDownloading(User, OCFile)}  and
-     *                     {@link FileUploaderBinder#isUploading(User, OCFile)} return false.
+     *                     {@link FileUploadHelper#isUploading(User, OCFile)} return false.
      * @param refresh      If 'true', try to refresh the whole file from the database
      * @param refresh      If 'true', try to refresh the whole file from the database
      */
      */
     public void updateFileDetails(boolean transferring, boolean refresh) {
     public void updateFileDetails(boolean transferring, boolean refresh) {
@@ -537,10 +537,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             setFavoriteIconStatus(file.isFavorite());
             setFavoriteIconStatus(file.isFavorite());
 
 
             // configure UI for depending upon local state of the file
             // configure UI for depending upon local state of the file
-            FileUploaderBinder uploaderBinder = containerActivity.getFileUploaderBinder();
             if (transferring
             if (transferring
                 || (FileDownloadHelper.Companion.instance().isDownloading(user, file))
                 || (FileDownloadHelper.Companion.instance().isDownloading(user, file))
-                || (uploaderBinder != null && uploaderBinder.isUploading(user, file))) {
+                || (FileUploadHelper.Companion.instance().isUploading(user, file))) {
                 setButtonsForTransferring();
                 setButtonsForTransferring();
 
 
             } else if (file.isDown()) {
             } else if (file.isDown()) {
@@ -661,11 +660,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             // show the progress bar for the transfer
             // show the progress bar for the transfer
             binding.progressBlock.setVisibility(View.VISIBLE);
             binding.progressBlock.setVisibility(View.VISIBLE);
             binding.progressText.setVisibility(View.VISIBLE);
             binding.progressText.setVisibility(View.VISIBLE);
-            FileUploaderBinder uploaderBinder = containerActivity.getFileUploaderBinder();
             if (FileDownloadHelper.Companion.instance().isDownloading(user, getFile())) {
             if (FileDownloadHelper.Companion.instance().isDownloading(user, getFile())) {
                 binding.progressText.setText(R.string.downloader_download_in_progress_ticker);
                 binding.progressText.setText(R.string.downloader_download_in_progress_ticker);
             } else {
             } else {
-                if (uploaderBinder != null && uploaderBinder.isUploading(user, getFile())) {
+                if (FileUploadHelper.Companion.instance().isUploading(user, getFile())) {
                     binding.progressText.setText(R.string.uploader_upload_in_progress_ticker);
                     binding.progressText.setText(R.string.uploader_upload_in_progress_ticker);
                 }
                 }
             }
             }
@@ -698,9 +696,15 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
                 containerActivity.getFileDownloadProgressListener().
                 containerActivity.getFileDownloadProgressListener().
                     addDataTransferProgressListener(progressListener, getFile());
                     addDataTransferProgressListener(progressListener, getFile());
             }
             }
-            if (containerActivity.getFileUploaderBinder() != null) {
-                containerActivity.getFileUploaderBinder().
-                    addDatatransferProgressListener(progressListener, user, getFile());
+
+            if (containerActivity.getFileUploaderHelper() != null) {
+                OCFile file = getFile();
+                if (user == null || file == null) {
+                    return;
+                }
+
+                String targetKey = FileUploadHelper.Companion.buildRemoteName(user.getAccountName(), file.getRemotePath());
+                containerActivity.getFileUploaderHelper().addUploadTransferProgressListener(progressListener, targetKey);
             }
             }
         } else {
         } else {
             Log_OC.d(TAG, "progressListener == null");
             Log_OC.d(TAG, "progressListener == null");
@@ -713,9 +717,15 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
                 containerActivity.getFileDownloadProgressListener().
                 containerActivity.getFileDownloadProgressListener().
                     removeDataTransferProgressListener(progressListener, getFile());
                     removeDataTransferProgressListener(progressListener, getFile());
             }
             }
-            if (containerActivity.getFileUploaderBinder() != null) {
-                containerActivity.getFileUploaderBinder().
-                    removeDatatransferProgressListener(progressListener, user, getFile());
+            if (containerActivity.getFileUploaderHelper() != null) {
+                OCFile file = getFile();
+
+                if (user == null || file == null) {
+                    return;
+                }
+
+                String targetKey = FileUploadHelper.Companion.buildRemoteName(user.getAccountName(), file.getRemotePath());
+                containerActivity.getFileUploaderHelper().removeUploadTransferProgressListener(progressListener, targetKey);
             }
             }
         }
         }
     }
     }

+ 3 - 4
app/src/main/java/com/owncloud/android/ui/fragment/FileFragment.java

@@ -26,7 +26,6 @@ import android.os.Bundle;
 
 
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.nextcloud.utils.extensions.BundleExtensionsKt;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 
 
 import androidx.annotation.Nullable;
 import androidx.annotation.Nullable;
@@ -106,7 +105,7 @@ public class FileFragment extends Fragment {
 
 
         } catch (ClassCastException e) {
         } catch (ClassCastException e) {
             throw new IllegalArgumentException(activity.toString() + " must implement " +
             throw new IllegalArgumentException(activity.toString() + " must implement " +
-                    ContainerActivity.class.getSimpleName(), e);
+                                                   ContainerActivity.class.getSimpleName(), e);
         }
         }
     }
     }
 
 
@@ -159,8 +158,8 @@ public class FileFragment extends Fragment {
          * This happens when a download or upload is started or ended for a file.
          * This happens when a download or upload is started or ended for a file.
          *
          *
          * This method is necessary by now to update the user interface of the double-pane layout
          * This method is necessary by now to update the user interface of the double-pane layout
-         * in tablets because methods {@link //FileDownloaderBinder # isDownloading(Account, OCFile)}
-         * and {@link FileUploaderBinder# isUploading(Account, OCFile)}
+         * in tablets because methods FileDownloaderBinder.isDownloading(Account, OCFile)
+         * and FilesUploadHelper.isUploading(Account, OCFile)
          * won't provide the needed response before the method where this is called finishes.
          * won't provide the needed response before the method where this is called finishes.
          *
          *
          * TODO Remove this when the transfer state of a file is kept in the database
          * TODO Remove this when the transfer state of a file is kept in the database

+ 9 - 5
app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -47,8 +47,9 @@ import android.webkit.MimeTypeMap;
 
 
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.User;
-import com.nextcloud.client.files.downloader.FileDownloadHelper;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.jobs.BackgroundJobManager;
+import com.nextcloud.client.jobs.download.FileDownloadHelper;
+import com.nextcloud.client.jobs.upload.FileUploadHelper;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.client.network.ConnectivityService;
 import com.nextcloud.java.util.Optional;
 import com.nextcloud.java.util.Optional;
 import com.nextcloud.utils.EditorUtils;
 import com.nextcloud.utils.EditorUtils;
@@ -59,7 +60,6 @@ import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.StreamMediaFileOperation;
 import com.owncloud.android.files.StreamMediaFileOperation;
-import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.files.CheckEtagRemoteOperation;
 import com.owncloud.android.lib.resources.files.CheckEtagRemoteOperation;
@@ -104,6 +104,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
+import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;
@@ -1010,9 +1011,12 @@ public class FileOperationsHelper {
             FileDownloadHelper.Companion.instance().cancelPendingOrCurrentDownloads(currentUser, files);
             FileDownloadHelper.Companion.instance().cancelPendingOrCurrentDownloads(currentUser, files);
         }
         }
 
 
-        FileUploaderBinder uploaderBinder = fileActivity.getFileUploaderBinder();
-        if (uploaderBinder != null && uploaderBinder.isUploading(currentUser, file)) {
-            uploaderBinder.cancel(currentUser.toPlatformAccount(), file);
+        if (FileUploadHelper.Companion.instance().isUploading(currentUser, file)) {
+            try {
+                FileUploadHelper.Companion.instance().cancelFileUpload(file.getRemotePath(), currentUser.getAccountName());
+            } catch (NoSuchElementException e) {
+                Log_OC.e(TAG, "Error cancelling current upload because user does not exist!");
+            }
         }
         }
     }
     }
 
 

+ 59 - 21
app/src/main/java/com/owncloud/android/utils/FilesUploadHelper.kt

@@ -22,16 +22,22 @@
 
 
 package com.owncloud.android.utils
 package com.owncloud.android.utils
 
 
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
+import com.google.common.util.concurrent.ListenableFuture
 import com.nextcloud.client.account.User
 import com.nextcloud.client.account.User
 import com.nextcloud.client.jobs.BackgroundJobManager
 import com.nextcloud.client.jobs.BackgroundJobManager
+import com.nextcloud.client.jobs.BackgroundJobManagerImpl
 import com.nextcloud.client.jobs.FilesUploadWorker
 import com.nextcloud.client.jobs.FilesUploadWorker
 import com.owncloud.android.MainApp
 import com.owncloud.android.MainApp
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.UploadsStorageManager
 import com.owncloud.android.datamodel.UploadsStorageManager
+import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus
 import com.owncloud.android.db.OCUpload
 import com.owncloud.android.db.OCUpload
 import com.owncloud.android.files.services.NameCollisionPolicy
 import com.owncloud.android.files.services.NameCollisionPolicy
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
 import com.owncloud.android.lib.common.utils.Log_OC
 import com.owncloud.android.lib.common.utils.Log_OC
+import java.util.concurrent.ExecutionException
 import javax.inject.Inject
 import javax.inject.Inject
 
 
 class FilesUploadHelper {
 class FilesUploadHelper {
@@ -45,6 +51,50 @@ class FilesUploadHelper {
         MainApp.getAppComponent().inject(this)
         MainApp.getAppComponent().inject(this)
     }
     }
 
 
+    companion object {
+        private val TAG = FilesUploadWorker::class.java.simpleName
+        val mBoundListeners = HashMap<String, OnDatatransferProgressListener>()
+
+        fun onTransferProgress(
+            accountName: String?,
+            remotePath: String?,
+            progressRate: Long,
+            totalTransferredSoFar: Long,
+            totalToTransfer: Long,
+            fileName: String?
+        ) {
+            if (accountName == null || remotePath == null) return
+
+            val key: String =
+                FilesUploadWorker.buildRemoteName(accountName, remotePath)
+            val boundListener = mBoundListeners[key]
+
+            boundListener?.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName)
+        }
+
+        fun isWorkScheduled(tag: String): Boolean {
+            val instance = WorkManager.getInstance(MainApp.getAppContext())
+            val statuses: ListenableFuture<List<WorkInfo>> = instance.getWorkInfosByTag(tag)
+            var running = false
+            var workInfoList: List<WorkInfo> = emptyList()
+
+            try {
+                workInfoList = statuses.get()
+            } catch (e: ExecutionException) {
+                Log_OC.d(TAG, "ExecutionException in isWorkScheduled: $e")
+            } catch (e: InterruptedException) {
+                Log_OC.d(TAG, "InterruptedException in isWorkScheduled: $e")
+            }
+
+            for (workInfo in workInfoList) {
+                val state = workInfo.state
+                running = running || (state == WorkInfo.State.RUNNING || state == WorkInfo.State.ENQUEUED)
+            }
+
+            return running
+        }
+    }
+
     @Suppress("LongParameterList")
     @Suppress("LongParameterList")
     fun uploadNewFiles(
     fun uploadNewFiles(
         user: User,
         user: User,
@@ -85,6 +135,15 @@ class FilesUploadHelper {
         backgroundJobManager.startFilesUploadJob(user)
         backgroundJobManager.startFilesUploadJob(user)
     }
     }
 
 
+    fun isUploading(user: User?, file: OCFile?): Boolean {
+        if (user == null || file == null || !isWorkScheduled(BackgroundJobManagerImpl.JOB_FILES_UPLOAD)) {
+            return false
+        }
+
+        val upload: OCUpload = uploadsStorageManager.getUploadByRemotePath(file.remotePath) ?: return false
+        return upload.uploadStatus == UploadStatus.UPLOAD_IN_PROGRESS
+    }
+
     fun uploadUpdatedFile(
     fun uploadUpdatedFile(
         user: User,
         user: User,
         existingFiles: Array<OCFile?>?,
         existingFiles: Array<OCFile?>?,
@@ -138,25 +197,4 @@ class FilesUploadHelper {
             mBoundListeners.remove(targetKey)
             mBoundListeners.remove(targetKey)
         }
         }
     }
     }
-
-    companion object Progress {
-        val mBoundListeners = HashMap<String, OnDatatransferProgressListener>()
-
-        fun onTransferProgress(
-            accountName: String?,
-            remotePath: String?,
-            progressRate: Long,
-            totalTransferredSoFar: Long,
-            totalToTransfer: Long,
-            fileName: String?
-        ) {
-            if (accountName == null || remotePath == null) return
-
-            val key: String =
-                FilesUploadWorker.buildRemoteName(accountName, remotePath)
-            val boundListener = mBoundListeners[key]
-
-            boundListener?.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName)
-        }
-    }
 }
 }