Browse Source

add offline file remove capability

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 5 months ago
parent
commit
a2d12f45ff

+ 10 - 0
app/src/main/java/com/nextcloud/client/database/typeAdapter/OfflineOperationTypeAdapter.kt

@@ -46,6 +46,11 @@ class OfflineOperationTypeAdapter : JsonSerializer<OfflineOperationType>, JsonDe
                 jsonObject.addProperty("newName", src.newName)
             }
 
+            is OfflineOperationType.RemoveFile -> {
+                jsonObject.addProperty("type", src.type)
+                jsonObject.addProperty("path", src.path)
+            }
+
             null -> Unit
         }
 
@@ -78,6 +83,11 @@ class OfflineOperationTypeAdapter : JsonSerializer<OfflineOperationType>, JsonDe
                 jsonObject.get("newName").asString
             )
 
+            OfflineOperationRawType.RemoveFile.name -> OfflineOperationType.RemoveFile(
+                jsonObject.get("type").asString,
+                jsonObject.get("path").asString
+            )
+
             else -> null
         }
     }

+ 20 - 1
app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt

@@ -25,6 +25,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult
 import com.owncloud.android.lib.common.utils.Log_OC
 import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation
 import com.owncloud.android.operations.CreateFolderOperation
+import com.owncloud.android.operations.RemoveFileOperation
 import com.owncloud.android.operations.RenameFileOperation
 import com.owncloud.android.utils.theme.ViewThemeUtils
 import kotlinx.coroutines.Dispatchers
@@ -163,6 +164,16 @@ class OfflineOperationsWorker(
                 renameFileOperation?.execute(client) to renameFileOperation
             }
 
+            is OfflineOperationType.RemoveFile -> {
+                val removeFileOperation = withContext(NonCancellable) {
+                    val operationType = (operation.type as OfflineOperationType.RemoveFile)
+                    val ocFile = fileDataStorageManager.getFileByDecryptedRemotePath(operationType.path)
+                    RemoveFileOperation(ocFile, false, user, true, context, fileDataStorageManager)
+                }
+
+                removeFileOperation.execute(client) to removeFileOperation
+            }
+
             else -> {
                 Log_OC.d(TAG, "Unsupported operation type: ${operation.type}")
                 null
@@ -186,7 +197,15 @@ class OfflineOperationsWorker(
         Log_OC.d(TAG, "$logMessage filename: ${operation.filename}, type: ${operation.type}")
 
         if (result.isSuccess) {
-            repository.updateNextOperations(operation)
+            if (operation.type is OfflineOperationType.RemoveFile) {
+                val operationType = operation.type as OfflineOperationType.RemoveFile
+                fileDataStorageManager.getFileByDecryptedRemotePath(operationType.path)?.let { ocFile ->
+                    repository.deleteOperation(ocFile)
+                }
+            } else {
+                repository.updateNextOperations(operation)
+            }
+
             fileDataStorageManager.offlineOperationDao.delete(operation)
             notificationManager.update(totalOperations, currentSuccessfulOperationIndex, operation.filename ?: "")
         } else {

+ 4 - 1
app/src/main/java/com/nextcloud/model/OfflineOperationType.kt

@@ -24,10 +24,13 @@ sealed class OfflineOperationType {
         var ocFileId: Long,
         val newName: String
     ) : OfflineOperationType()
+
+    data class RemoveFile(override val type: String, var path: String) : OfflineOperationType()
 }
 
 enum class OfflineOperationRawType {
     CreateFolder,
     CreateFile,
-    RenameFile
+    RenameFile,
+    RemoveFile
 }

+ 23 - 0
app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -175,6 +175,10 @@ public class FileDataStorageManager {
         }
     }
 
+    public OfflineOperationEntity getOfflineEntityFromOCFile(OCFile file) {
+        return offlineOperationDao.getByPath(file.getDecryptedRemotePath());
+    }
+
     public OfflineOperationEntity addCreateFolderOfflineOperation(String path, String filename, Long parentOCFileId) {
         OfflineOperationEntity entity = new OfflineOperationEntity();
 
@@ -246,6 +250,25 @@ public class FileDataStorageManager {
         return filename;
     }
 
+    public void addRemoveFileOfflineOperation(String path, String filename, Long parentOCFileId) {
+        OfflineOperationEntity entity = new OfflineOperationEntity();
+
+        entity.setFilename(filename);
+        entity.setParentOCFileId(parentOCFileId);
+
+        OfflineOperationType.RemoveFile operationType = new OfflineOperationType.RemoveFile(OfflineOperationRawType.RemoveFile.name(), path);
+        entity.setType(operationType);
+        entity.setPath(path);
+
+        long createdAt = System.currentTimeMillis();
+        long modificationTimestamp = System.currentTimeMillis();
+
+        entity.setCreatedAt(createdAt);
+        entity.setModifiedAt(modificationTimestamp / 1000);
+
+        offlineOperationDao.insert(entity);
+    }
+
     public void renameOfflineOperation(OCFile file, String newFolderName) {
         var entity = offlineOperationDao.getByPath(file.getDecryptedRemotePath());
         if (entity == null) {

+ 24 - 19
app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java

@@ -607,28 +607,11 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
                 localSize = localFile.length();
             }
 
-            holder.getFileSize().setVisibility(View.VISIBLE);
-
-
-            if (file.isOfflineOperation()) {
-                holder.getFileSize().setText(MainApp.string(R.string.oc_file_list_adapter_offline_operation_description_text));
-            } else {
-                holder.getFileSize().setText(DisplayUtils.bytesToHumanReadable(localSize));
-            }
-
-            holder.getFileSizeSeparator().setVisibility(View.VISIBLE);
+            prepareFileSize(holder, file, localSize);
         } else {
             final long fileLength = file.getFileLength();
             if (fileLength >= 0) {
-                holder.getFileSize().setVisibility(View.VISIBLE);
-
-                if (file.isOfflineOperation()) {
-                    holder.getFileSize().setText(MainApp.string(R.string.oc_file_list_adapter_offline_operation_description_text));
-                } else {
-                    holder.getFileSize().setText(DisplayUtils.bytesToHumanReadable(fileLength));
-                }
-
-                holder.getFileSizeSeparator().setVisibility(View.VISIBLE);
+                prepareFileSize(holder, file, fileLength);
             } else {
                 holder.getFileSize().setVisibility(View.GONE);
                 holder.getFileSizeSeparator().setVisibility(View.GONE);
@@ -666,6 +649,28 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
         applyVisualsForOfflineOperations(holder, file);
     }
 
+    private void prepareFileSize(ListItemViewHolder holder, OCFile file, long size) {
+        holder.getFileSize().setVisibility(View.VISIBLE);
+        ViewExtensionsKt.setVisibleIf(holder.getFileSizeSeparator(), !file.isOfflineOperation());
+        String fileSizeText = getFileSizeText(file, size);
+        holder.getFileSize().setText(fileSizeText);
+    }
+
+    private String getFileSizeText(OCFile file, long size) {
+        OfflineOperationEntity entity = mStorageManager.getOfflineEntityFromOCFile(file);
+        boolean isRemoveOperation = entity != null && entity.getType() instanceof OfflineOperationType.RemoveFile;
+
+        if (isRemoveOperation) {
+            return activity.getString(R.string.oc_file_list_adapter_offline_operation_remove_description_text);
+        }
+
+        if (file.isOfflineOperation()) {
+            return activity.getString(R.string.oc_file_list_adapter_offline_operation_description_text);
+        }
+
+        return DisplayUtils.bytesToHumanReadable(size);
+    }
+
     private void applyVisualsForOfflineOperations(ListItemViewHolder holder, OCFile file) {
         ViewExtensionsKt.setVisibleIf(holder.getShared(), !file.isOfflineOperation());
 

+ 25 - 9
app/src/main/java/com/owncloud/android/ui/dialog/RemoveFilesDialogFragment.kt

@@ -90,17 +90,33 @@ class RemoveFilesDialogFragment : ConfirmationDialogFragment(), ConfirmationDial
             fileDataStorageManager.deleteOfflineOperation(it)
         }
 
-        if (files.isNotEmpty()) {
-            val cg = activity as ComponentsGetter?
-            cg?.fileOperationsHelper?.removeFiles(files, onlyLocalCopy, false)
-        }
+        if (requireActivity() is FileDisplayActivity) {
+            val activity = requireActivity() as FileDisplayActivity
+            activity.connectivityService.isNetworkAndServerAvailable { result ->
+                if (result) {
+                    if (files.isNotEmpty()) {
+                        val cg = activity as ComponentsGetter?
+                        cg?.fileOperationsHelper?.removeFiles(files, onlyLocalCopy, false)
+                    }
 
-        if (offlineFiles.isNotEmpty()) {
-            val activity = requireActivity() as? FileDisplayActivity
-            activity?.refreshCurrentDirectory()
-        }
+                    if (offlineFiles.isNotEmpty()) {
+                        activity.refreshCurrentDirectory()
+                    }
+                } else {
+                    files.forEach { file ->
+                        fileDataStorageManager.addRemoveFileOfflineOperation(
+                            file.decryptedRemotePath,
+                            file.fileName,
+                            file.parentId
+                        )
+                    }
+
+                    activity.refreshCurrentDirectory()
+                }
 
-        finishActionMode()
+                finishActionMode()
+            }
+        }
     }
 
     override fun onNeutral(callerTag: String?) {

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -1263,4 +1263,6 @@
     <string name="two_way_sync_activity_empty_list_desc">To set up a two way sync folder, please enable it in the details tab of the folder in question.</string>
     <string name="two_way_sync_activity_title">Internal two way sync</string>
     <string name="two_way_sync_activity_disable_all_button_title">Disable for all folders</string>
+
+    <string name="oc_file_list_adapter_offline_operation_remove_description_text">Pending Remove Operation</string>
 </resources>