From 79e651874a9469a404fb39ef1f731f9b3192f745 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 5 Apr 2024 09:58:19 +0200 Subject: [PATCH 001/114] Delete temp encryptedFile in all cases Signed-off-by: alperozturk --- .../com/owncloud/android/util/EncryptionTestIT.java | 2 +- .../android/operations/UploadFileOperation.java | 13 +++++++------ .../com/owncloud/android/utils/EncryptionUtils.java | 3 +-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java b/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java index d1100a8b97aa..b077e8b9c007 100644 --- a/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java +++ b/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java @@ -836,7 +836,7 @@ private boolean cryptFile(String fileName, String md5, byte[] key, byte[] iv) // Encryption Cipher encryptorCipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv); - EncryptionUtils.encryptFile(file, encryptorCipher); + EncryptionUtils.encryptFile(targetContext, file, encryptorCipher); String encryptorCipherAuthTag = EncryptionUtils.getAuthenticationTag(encryptorCipher); // Decryption diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 5c2e793001dc..e2f8e03ac11d 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -442,6 +442,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare File temporalFile = null; File originalFile = new File(mOriginalStoragePath); File expectedFile = null; + File encryptedTempFile = null; FileLock fileLock = null; long size; @@ -552,7 +553,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare byte[] iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength); Cipher cipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv); File file = new File(mFile.getStoragePath()); - EncryptedFile encryptedFile = EncryptionUtils.encryptFile(file, cipher); + EncryptedFile encryptedFile = EncryptionUtils.encryptFile(getContext(), file, cipher); // new random file name, check if it exists in metadata String encryptedFileName = EncryptionUtils.generateUid(); @@ -567,9 +568,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare } } - File encryptedTempFile = encryptedFile.getEncryptedFile(); - - /***** E2E *****/ + encryptedTempFile = encryptedFile.getEncryptedFile(); FileChannel channel = null; try { @@ -712,8 +711,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare user, getStorageManager()); } - - encryptedTempFile.delete(); } } catch (FileNotFoundException e) { Log_OC.d(TAG, mFile.getStoragePath() + " not exists anymore"); @@ -755,6 +752,10 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare if (unlockFolderResult != null && !unlockFolderResult.isSuccess()) { result = unlockFolderResult; } + + boolean isTempEncryptedFileDeleted = encryptedTempFile.delete(); + Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted); + } if (result.isSuccess()) { diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index aebe37816a72..a91b038fd831 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -547,8 +547,7 @@ public static byte[] decodeStringToBase64Bytes(String string) { return Base64.decode(string, Base64.NO_WRAP); } - public static EncryptedFile encryptFile(File file, Cipher cipher) throws InvalidParameterSpecException { - // FIXME this won't work on low or write-protected storage + public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException { File encryptedFile = new File(file.getAbsolutePath() + ".enc.jpg"); encryptFileWithGivenCipher(file, encryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); From c6c646063027ca04fe770e9e3c55772a19b1948e Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 5 Apr 2024 10:13:59 +0200 Subject: [PATCH 002/114] Use temp directory for tempEncryptedFile creation Signed-off-by: alperozturk --- .../java/com/owncloud/android/utils/EncryptionUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index a91b038fd831..f49991524d70 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -547,11 +547,11 @@ public static byte[] decodeStringToBase64Bytes(String string) { return Base64.decode(string, Base64.NO_WRAP); } - public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException { - File encryptedFile = new File(file.getAbsolutePath() + ".enc.jpg"); - encryptFileWithGivenCipher(file, encryptedFile, cipher); + public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { + File tempEncryptedFile = File.createTempFile(file.getName(), "", context.getCacheDir()); + encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); - return new EncryptedFile(encryptedFile, authenticationTagString); + return new EncryptedFile(tempEncryptedFile, authenticationTagString); } public static String getAuthenticationTag(Cipher cipher) throws InvalidParameterSpecException { From 6515602ee61b0a8062470a4b8a2a8b517464a3c4 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 5 Apr 2024 10:39:45 +0200 Subject: [PATCH 003/114] Fix file name in notification Signed-off-by: alperozturk --- .../client/jobs/upload/FileUploadWorker.kt | 41 ++++++++++--------- .../jobs/upload/UploadNotificationManager.kt | 12 +++--- .../operations/UploadFileOperation.java | 6 ++- .../android/utils/EncryptionUtils.java | 2 +- 4 files changed, 32 insertions(+), 29 deletions(-) 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 e0c50de8c3bb..5ea59f0660e3 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 @@ -165,16 +165,16 @@ class FileUploadWorker( } if (user.isPresent) { - val operation = createUploadFileOperation(upload, user.get()) + val uploadFileOperation = createUploadFileOperation(upload, user.get()) - currentUploadFileOperation = operation - val result = upload(operation, user.get()) + currentUploadFileOperation = uploadFileOperation + val result = upload(uploadFileOperation, user.get()) currentUploadFileOperation = null fileUploaderDelegate.sendBroadcastUploadFinished( - operation, + uploadFileOperation, result, - operation.oldFile?.storagePath, + uploadFileOperation.oldFile?.storagePath, context, localBroadcastManager ) @@ -205,39 +205,39 @@ class FileUploadWorker( } @Suppress("TooGenericExceptionCaught", "DEPRECATION") - private fun upload(operation: UploadFileOperation, user: User): RemoteOperationResult { + private fun upload(uploadFileOperation: UploadFileOperation, user: User): RemoteOperationResult { lateinit var result: RemoteOperationResult notificationManager.prepareForStart( - operation, - intents.startIntent(operation), - intents.notificationStartIntent(operation) + uploadFileOperation, + intents.startIntent(uploadFileOperation), + intents.notificationStartIntent(uploadFileOperation) ) try { - val storageManager = operation.storageManager + val storageManager = uploadFileOperation.storageManager val ocAccount = OwnCloudAccount(user.toPlatformAccount(), context) val uploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context) - result = operation.execute(uploadClient) + result = uploadFileOperation.execute(uploadClient) val task = ThumbnailsCacheManager.ThumbnailGenerationTask(storageManager, user) - val file = File(operation.originalStoragePath) - val remoteId: String? = operation.file.remoteId + val file = File(uploadFileOperation.originalStoragePath) + val remoteId: String? = uploadFileOperation.file.remoteId task.execute(ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId)) } catch (e: Exception) { Log_OC.e(TAG, "Error uploading", e) result = RemoteOperationResult(e) } finally { - cleanupUploadProcess(result, operation) + cleanupUploadProcess(result, uploadFileOperation) } return result } - private fun cleanupUploadProcess(result: RemoteOperationResult, operation: UploadFileOperation) { + private fun cleanupUploadProcess(result: RemoteOperationResult, uploadFileOperation: UploadFileOperation) { if (!isStopped || !result.isCancelled) { - uploadsStorageManager.updateDatabaseUploadResult(result, operation) - notifyUploadResult(operation, result) + uploadsStorageManager.updateDatabaseUploadResult(result, uploadFileOperation) + notifyUploadResult(uploadFileOperation, result) notificationManager.dismissWorkerNotifications() } } @@ -315,10 +315,11 @@ class FileUploadWorker( if (percent != lastPercent) { notificationManager.run { - updateUploadProgress(fileAbsoluteName, percent, currentUploadFileOperation) - val accountName = currentUploadFileOperation?.user?.accountName val remotePath = currentUploadFileOperation?.remotePath + val filename = currentUploadFileOperation?.fileName ?: "" + + updateUploadProgress(filename, percent, currentUploadFileOperation) if (accountName != null && remotePath != null) { val key: String = @@ -329,7 +330,7 @@ class FileUploadWorker( progressRate, totalTransferredSoFar, totalToTransfer, - fileAbsoluteName + filename ) } diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt index 23392fa65a6b..a4c3f28fee96 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt @@ -16,7 +16,6 @@ import android.os.Build import androidx.core.app.NotificationCompat import com.owncloud.android.R import com.owncloud.android.lib.common.operations.RemoteOperationResult -import com.owncloud.android.lib.resources.files.FileUtils import com.owncloud.android.operations.UploadFileOperation import com.owncloud.android.ui.notifications.NotificationUtils import com.owncloud.android.utils.theme.ViewThemeUtils @@ -44,14 +43,14 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi } @Suppress("MagicNumber") - fun prepareForStart(upload: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) { + fun prepareForStart(uploadFileOperation: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) { notificationBuilder.run { setContentTitle(context.getString(R.string.uploader_upload_in_progress_ticker)) setContentText( String.format( context.getString(R.string.uploader_upload_in_progress), 0, - upload.fileName + uploadFileOperation.fileName ) ) setTicker(context.getString(R.string.foreground_service_upload)) @@ -68,7 +67,7 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi setContentIntent(startIntent) } - if (!upload.isInstantPicture && !upload.isInstantVideo) { + if (!uploadFileOperation.isInstantPicture && !uploadFileOperation.isInstantVideo) { showNotification() } } @@ -138,11 +137,10 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi } @Suppress("MagicNumber") - fun updateUploadProgress(filePath: String, percent: Int, currentOperation: UploadFileOperation?) { + fun updateUploadProgress(filename: String, percent: Int, currentOperation: UploadFileOperation?) { notificationBuilder.run { setProgress(100, percent, false) - val fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1) - val text = String.format(context.getString(R.string.uploader_upload_in_progress), percent, fileName) + val text = String.format(context.getString(R.string.uploader_upload_in_progress), percent, filename) setContentText(text) showNotification() diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index e2f8e03ac11d..61a2f2e4fa53 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -272,7 +272,11 @@ public User getUser() { } public String getFileName() { - return (mFile != null) ? mFile.getFileName() : null; + if (mFile == null) { + return null; + } + + return mFile.getFileName(); } public OCFile getFile() { diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index f49991524d70..dfe8fdfa1a29 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -548,7 +548,7 @@ public static byte[] decodeStringToBase64Bytes(String string) { } public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - File tempEncryptedFile = File.createTempFile(file.getName(), "", context.getCacheDir()); + File tempEncryptedFile = File.createTempFile(file.getName(), ".", context.getCacheDir()); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); return new EncryptedFile(tempEncryptedFile, authenticationTagString); From 0e47ad737f6f82c4965c08dca964efb938467b41 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 5 Apr 2024 10:48:42 +0200 Subject: [PATCH 004/114] Use single line code for getFileName Signed-off-by: alperozturk --- .../owncloud/android/operations/UploadFileOperation.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 61a2f2e4fa53..e2f8e03ac11d 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -272,11 +272,7 @@ public User getUser() { } public String getFileName() { - if (mFile == null) { - return null; - } - - return mFile.getFileName(); + return (mFile != null) ? mFile.getFileName() : null; } public OCFile getFile() { From 17f7676abbc782d79c2cb279e5b6bdf31e7f2976 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 8 Apr 2024 16:32:10 +0200 Subject: [PATCH 005/114] Fix code analytics Signed-off-by: alperozturk --- .../client/jobs/upload/UploadNotificationManager.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt index a4c3f28fee96..a6d74ce7e152 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt @@ -43,7 +43,11 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi } @Suppress("MagicNumber") - fun prepareForStart(uploadFileOperation: UploadFileOperation, pendingIntent: PendingIntent, startIntent: PendingIntent) { + fun prepareForStart( + uploadFileOperation: UploadFileOperation, + pendingIntent: PendingIntent, + startIntent: PendingIntent + ) { notificationBuilder.run { setContentTitle(context.getString(R.string.uploader_upload_in_progress_ticker)) setContentText( From 9c5d39f30118452e1fba622df3818be89d38aa7a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 9 Apr 2024 09:31:27 +0200 Subject: [PATCH 006/114] Fix code analytics Signed-off-by: alperozturk --- .../owncloud/android/operations/UploadFileOperation.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index e2f8e03ac11d..1e805c244e6d 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -753,9 +753,12 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare result = unlockFolderResult; } - boolean isTempEncryptedFileDeleted = encryptedTempFile.delete(); - Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted); - + if (encryptedTempFile != null) { + boolean isTempEncryptedFileDeleted = encryptedTempFile.delete(); + Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted); + } else { + Log_OC.e(TAG, "Encrypted temp file cannot be found"); + } } if (result.isSuccess()) { From 14d3257036c8c22c6872912a597f923eb791bb92 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 11:49:09 +0200 Subject: [PATCH 007/114] Remove "." suffix Signed-off-by: alperozturk --- .../main/java/com/owncloud/android/utils/EncryptionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index dfe8fdfa1a29..47817eb71d83 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -548,7 +548,7 @@ public static byte[] decodeStringToBase64Bytes(String string) { } public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - File tempEncryptedFile = File.createTempFile(file.getName(), ".", context.getCacheDir()); + File tempEncryptedFile = File.createTempFile(file.getName(), null, context.getCacheDir()); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); return new EncryptedFile(tempEncryptedFile, authenticationTagString); From a563c87b0116418eada2ab4f3c008d92d1746cbc Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 11:52:46 +0200 Subject: [PATCH 008/114] Delete temporal file usage for e2e Signed-off-by: alperozturk --- .../operations/UploadFileOperation.java | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 1e805c244e6d..1629b5f7847a 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -439,7 +439,6 @@ protected RemoteOperationResult run(OwnCloudClient client) { @SuppressLint("AndroidLintUseSparseArrays") // gson cannot handle sparse arrays easily, therefore use hashmap private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile parentFile) { RemoteOperationResult result = null; - File temporalFile = null; File originalFile = new File(mOriginalStoragePath); File expectedFile = null; File encryptedTempFile = null; @@ -580,14 +579,14 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) + mFile.getRemotePath(); mFile.setStoragePath(temporalPath); - temporalFile = new File(temporalPath); + encryptedTempFile = new File(temporalPath); Files.deleteIfExists(Paths.get(temporalPath)); - result = copy(originalFile, temporalFile); + result = copy(originalFile, encryptedTempFile); if (result.isSuccess()) { - if (temporalFile.length() == originalFile.length()) { - channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel(); + if (encryptedTempFile.length() == originalFile.length()) { + channel = new RandomAccessFile(encryptedTempFile.getAbsolutePath(), "rw").getChannel(); fileLock = channel.tryLock(); } else { result = new RemoteOperationResult(ResultCode.LOCK_FAILED); @@ -732,9 +731,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare } } - if (temporalFile != null && !originalFile.equals(temporalFile)) { - temporalFile.delete(); - } if (result == null) { result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); } @@ -753,6 +749,12 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare result = unlockFolderResult; } + if (result.isSuccess()) { + handleSuccessfulUpload(encryptedTempFile, expectedFile, originalFile, client); + } else if (result.getCode() == ResultCode.SYNC_CONFLICT) { + getStorageManager().saveConflict(mFile, mFile.getEtagInConflict()); + } + if (encryptedTempFile != null) { boolean isTempEncryptedFileDeleted = encryptedTempFile.delete(); Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted); @@ -761,17 +763,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare } } - if (result.isSuccess()) { - handleSuccessfulUpload(temporalFile, expectedFile, originalFile, client); - } else if (result.getCode() == ResultCode.SYNC_CONFLICT) { - getStorageManager().saveConflict(mFile, mFile.getEtagInConflict()); - } - - // delete temporal file - if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) { - Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath()); - } - return result; } From d583a2f62c598ca96582b08e2ad0d4805ad370d9 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 12:37:12 +0200 Subject: [PATCH 009/114] Revert changes Signed-off-by: alperozturk --- .../operations/UploadFileOperation.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 1629b5f7847a..1e805c244e6d 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -439,6 +439,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { @SuppressLint("AndroidLintUseSparseArrays") // gson cannot handle sparse arrays easily, therefore use hashmap private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile parentFile) { RemoteOperationResult result = null; + File temporalFile = null; File originalFile = new File(mOriginalStoragePath); File expectedFile = null; File encryptedTempFile = null; @@ -579,14 +580,14 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare String temporalPath = FileStorageUtils.getInternalTemporalPath(user.getAccountName(), mContext) + mFile.getRemotePath(); mFile.setStoragePath(temporalPath); - encryptedTempFile = new File(temporalPath); + temporalFile = new File(temporalPath); Files.deleteIfExists(Paths.get(temporalPath)); - result = copy(originalFile, encryptedTempFile); + result = copy(originalFile, temporalFile); if (result.isSuccess()) { - if (encryptedTempFile.length() == originalFile.length()) { - channel = new RandomAccessFile(encryptedTempFile.getAbsolutePath(), "rw").getChannel(); + if (temporalFile.length() == originalFile.length()) { + channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel(); fileLock = channel.tryLock(); } else { result = new RemoteOperationResult(ResultCode.LOCK_FAILED); @@ -731,6 +732,9 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare } } + if (temporalFile != null && !originalFile.equals(temporalFile)) { + temporalFile.delete(); + } if (result == null) { result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); } @@ -749,12 +753,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare result = unlockFolderResult; } - if (result.isSuccess()) { - handleSuccessfulUpload(encryptedTempFile, expectedFile, originalFile, client); - } else if (result.getCode() == ResultCode.SYNC_CONFLICT) { - getStorageManager().saveConflict(mFile, mFile.getEtagInConflict()); - } - if (encryptedTempFile != null) { boolean isTempEncryptedFileDeleted = encryptedTempFile.delete(); Log_OC.e(TAG, "isTempEncryptedFileDeleted: " + isTempEncryptedFileDeleted); @@ -763,6 +761,17 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare } } + if (result.isSuccess()) { + handleSuccessfulUpload(temporalFile, expectedFile, originalFile, client); + } else if (result.getCode() == ResultCode.SYNC_CONFLICT) { + getStorageManager().saveConflict(mFile, mFile.getEtagInConflict()); + } + + // delete temporal file + if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) { + Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath()); + } + return result; } From 123c576399d1e1782e3a621416bbc5e8485dd088 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 16:38:22 +0200 Subject: [PATCH 010/114] Dont use cache dir. cache dir might be deleted during big file uploads Signed-off-by: alperozturk --- .../main/java/com/owncloud/android/utils/EncryptionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index 47817eb71d83..acb9da6c7297 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -548,7 +548,7 @@ public static byte[] decodeStringToBase64Bytes(String string) { } public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - File tempEncryptedFile = File.createTempFile(file.getName(), null, context.getCacheDir()); + File tempEncryptedFile = File.createTempFile(file.getName(), null, context.getFilesDir()); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); return new EncryptedFile(tempEncryptedFile, authenticationTagString); From 39e9916732ad4e32d9dc84bc0de1e5c5c4826ca0 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 16:43:13 +0200 Subject: [PATCH 011/114] Use tempEncryptedFolder Signed-off-by: alperozturk --- .../owncloud/android/utils/EncryptionUtils.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index acb9da6c7297..875309fe7787 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -548,7 +548,17 @@ public static byte[] decodeStringToBase64Bytes(String string) { } public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - File tempEncryptedFile = File.createTempFile(file.getName(), null, context.getFilesDir()); + String dirPath = context.getFilesDir().getAbsolutePath() + File.separator + "temp_encrypted_folder"; + File tempEncryptedFolder = new File(dirPath); + + if (!tempEncryptedFolder.exists()) { + boolean isTempEncryptedFolderCreated = tempEncryptedFolder.mkdirs(); + Log_OC.d(TAG, "tempEncryptedFolder created" + isTempEncryptedFolderCreated); + } else { + Log_OC.d(TAG, "tempEncryptedFolder already exists"); + } + + File tempEncryptedFile = File.createTempFile(file.getName(), null, tempEncryptedFolder); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); return new EncryptedFile(tempEncryptedFile, authenticationTagString); @@ -568,7 +578,7 @@ public static Cipher getCipher(int mode, byte[] encryptionKeyBytes, byte[] iv) t } public static void encryptFileWithGivenCipher(File inputFile, File encryptedFile, Cipher cipher) { - try( FileInputStream inputStream = new FileInputStream(inputFile); + try (FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream fileOutputStream = new FileOutputStream(encryptedFile); CipherOutputStream outputStream = new CipherOutputStream(fileOutputStream, cipher)) { byte[] buffer = new byte[4096]; From 7470fef2d6065fea4518ceaf7151b6ddf47baefd Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 16:55:35 +0200 Subject: [PATCH 012/114] Clear temp directory for cancelling all uploads Signed-off-by: alperozturk --- .../datamodel/FileDataStorageManager.java | 40 +++++++++++++++++++ .../android/ui/adapter/UploadListAdapter.java | 4 ++ .../android/utils/EncryptionUtils.java | 11 +---- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 6245958506ad..9a86353ff0c4 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -56,7 +56,10 @@ import com.owncloud.android.utils.MimeType; import com.owncloud.android.utils.MimeTypeUtil; +import org.apache.commons.io.FileUtils; + import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -338,6 +341,43 @@ public OCFile saveFileWithParent(OCFile ocFile, Context context) { return ocFile; } + private static final String tempEncryptedFolderPath = "temp_encrypted_folder"; + + public static void clearTempEncryptedFolder(Context context) { + File tempEncryptedFolder = getTempEncryptedFolder(context); + + if (!tempEncryptedFolder.exists()) { + Log_OC.d(TAG,"tempEncryptedFolder not exists"); + return; + } + + try { + FileUtils.cleanDirectory(tempEncryptedFolder); + + Log_OC.d(TAG,"tempEncryptedFolder cleared"); + } catch (IOException exception) { + Log_OC.d(TAG,"Error caught at clearTempEncryptedFolder: " + exception); + } + } + + public static File getTempEncryptedFolder(Context context) { + String dirPath = context.getFilesDir().getAbsolutePath() + File.separator + tempEncryptedFolderPath; + return new File(dirPath); + } + + public static File createTempEncryptedFolder(Context context) { + File tempEncryptedFolder = getTempEncryptedFolder(context); + + if (!tempEncryptedFolder.exists()) { + boolean isTempEncryptedFolderCreated = tempEncryptedFolder.mkdirs(); + Log_OC.d(TAG, "tempEncryptedFolder created" + isTempEncryptedFolderCreated); + } else { + Log_OC.d(TAG, "tempEncryptedFolder already exists"); + } + + return tempEncryptedFolder; + } + public void saveNewFile(OCFile newFile) { String remoteParentPath = new File(newFile.getRemotePath()).getParent(); remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java index 2a747669bd58..3d5a5ad61004 100755 --- a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java @@ -54,6 +54,8 @@ import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.theme.ViewThemeUtils; +import org.apache.commons.io.FileUtils; + import java.io.File; import java.util.Arrays; import java.util.Optional; @@ -169,6 +171,8 @@ private void showCancelledPopupMenu(HeaderViewHolder headerViewHolder) { if (itemId == R.id.action_upload_list_cancelled_clear) { uploadsStorageManager.clearCancelledUploadsForCurrentAccount(); loadUploadItemsFromDb(); + + FileDataStorageManager.clearTempEncryptedFolder(parentActivity); } else if (itemId == R.id.action_upload_list_cancelled_resume) { retryCancelledUploads(); } diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index 875309fe7787..0a10af4f8033 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -548,16 +548,7 @@ public static byte[] decodeStringToBase64Bytes(String string) { } public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - String dirPath = context.getFilesDir().getAbsolutePath() + File.separator + "temp_encrypted_folder"; - File tempEncryptedFolder = new File(dirPath); - - if (!tempEncryptedFolder.exists()) { - boolean isTempEncryptedFolderCreated = tempEncryptedFolder.mkdirs(); - Log_OC.d(TAG, "tempEncryptedFolder created" + isTempEncryptedFolderCreated); - } else { - Log_OC.d(TAG, "tempEncryptedFolder already exists"); - } - + File tempEncryptedFolder = FileDataStorageManager.createTempEncryptedFolder(context); File tempEncryptedFile = File.createTempFile(file.getName(), null, tempEncryptedFolder); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); From a7fe0adafbaa0d307ccfa36bf8bbcf0a4c41112c Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 09:03:27 +0200 Subject: [PATCH 013/114] Use more clear argument names Signed-off-by: alperozturk --- .../java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt | 2 +- .../nextcloud/client/jobs/upload/UploadNotificationManager.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 5ea59f0660e3..80cb01ee4eb8 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 @@ -210,7 +210,7 @@ class FileUploadWorker( notificationManager.prepareForStart( uploadFileOperation, - intents.startIntent(uploadFileOperation), + cancelPendingIntent = intents.startIntent(uploadFileOperation), intents.notificationStartIntent(uploadFileOperation) ) diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt index a6d74ce7e152..4c2a9c6656ba 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/UploadNotificationManager.kt @@ -45,7 +45,7 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi @Suppress("MagicNumber") fun prepareForStart( uploadFileOperation: UploadFileOperation, - pendingIntent: PendingIntent, + cancelPendingIntent: PendingIntent, startIntent: PendingIntent ) { notificationBuilder.run { @@ -65,7 +65,7 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi addAction( R.drawable.ic_action_cancel_grey, context.getString(R.string.common_cancel), - pendingIntent + cancelPendingIntent ) setContentIntent(startIntent) From 24b2d033f18eb59aa7e7ba029dc60a2d4f8d58f6 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 09:28:43 +0200 Subject: [PATCH 014/114] Clear temp encrypted folder for clear failed uploads actions Signed-off-by: alperozturk --- .../java/com/owncloud/android/ui/adapter/UploadListAdapter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java index 3d5a5ad61004..378d1995bbbf 100755 --- a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java @@ -143,6 +143,7 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { if (itemId == R.id.action_upload_list_failed_clear) { uploadsStorageManager.clearFailedButNotDelayedUploads(); + FileDataStorageManager.clearTempEncryptedFolder(MainApp.getAppContext()); loadUploadItemsFromDb(); } else { From c78a67d53cda19e1ca8cc5df7f887b1271bae021 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 09:29:57 +0200 Subject: [PATCH 015/114] Specifically make visible retry failed uploads action Signed-off-by: alperozturk --- .../com/owncloud/android/ui/adapter/UploadListAdapter.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java index 378d1995bbbf..3436e6e96d48 100755 --- a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java @@ -145,8 +145,7 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { uploadsStorageManager.clearFailedButNotDelayedUploads(); FileDataStorageManager.clearTempEncryptedFolder(MainApp.getAppContext()); loadUploadItemsFromDb(); - } else { - + } else if (itemId == R.id.action_upload_list_failed_retry) { new Thread(() -> { FileUploadHelper.Companion.instance().retryFailedUploads( uploadsStorageManager, @@ -155,8 +154,8 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { powerManagementService); parentActivity.runOnUiThread(this::loadUploadItemsFromDb); }).start(); - } + return true; }); failedPopup.show(); From 80b40b947cefa18d13519189611f6fde6b1cdfc0 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 09:31:26 +0200 Subject: [PATCH 016/114] Add fixme comments Signed-off-by: alperozturk --- .../com/owncloud/android/ui/adapter/UploadListAdapter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java index 3436e6e96d48..ab27688bd570 100755 --- a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java @@ -146,6 +146,8 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { FileDataStorageManager.clearTempEncryptedFolder(MainApp.getAppContext()); loadUploadItemsFromDb(); } else if (itemId == R.id.action_upload_list_failed_retry) { + + // FIXME For e2e resume is not working new Thread(() -> { FileUploadHelper.Companion.instance().retryFailedUploads( uploadsStorageManager, @@ -158,6 +160,7 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { return true; }); + failedPopup.show(); } @@ -183,6 +186,7 @@ private void showCancelledPopupMenu(HeaderViewHolder headerViewHolder) { popup.show(); } + // FIXME For e2e resume is not working private void retryCancelledUploads() { new Thread(() -> { boolean showNotExistMessage = FileUploadHelper.Companion.instance().retryCancelledUploads( From 7342b54f42b53cb106a7f50d390375fd47cb3792 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 09:53:47 +0200 Subject: [PATCH 017/114] Add log for failed uploads Signed-off-by: alperozturk --- .../java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt index 1b5f1c86675b..2e231b2def87 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt @@ -75,8 +75,10 @@ class FileUploadHelper { ) { val failedUploads = uploadsStorageManager.failedUploads if (failedUploads == null || failedUploads.isEmpty()) { + Log_OC.d(TAG, "Failed uploads are empty or null") return } + retryUploads( uploadsStorageManager, connectivityService, @@ -120,6 +122,7 @@ class FileUploadHelper { val charging = batteryStatus.isCharging || batteryStatus.isFull val isPowerSaving = powerManagementService.isPowerSavingEnabled var uploadUser = Optional.empty() + for (failedUpload in failedUploads) { // 1. extract failed upload owner account and cache it between loops (expensive query) if (!uploadUser.isPresent || !uploadUser.get().nameEquals(failedUpload.accountName)) { From 80e581bcd38db7f1d714f3ba23c2940076860436 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Fri, 12 Apr 2024 12:23:19 +0200 Subject: [PATCH 018/114] Use path for each user Signed-off-by: alperozturk --- .../owncloud/android/util/EncryptionTestIT.java | 2 +- .../android/datamodel/FileDataStorageManager.java | 15 ++++----------- .../android/operations/UploadFileOperation.java | 2 +- .../android/ui/adapter/UploadListAdapter.java | 12 +++++++----- .../owncloud/android/utils/EncryptionUtils.java | 4 ++-- .../owncloud/android/utils/FileStorageUtils.java | 11 +++++++++++ 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java b/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java index b077e8b9c007..8c81d28e5cdf 100644 --- a/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java +++ b/app/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java @@ -836,7 +836,7 @@ private boolean cryptFile(String fileName, String md5, byte[] key, byte[] iv) // Encryption Cipher encryptorCipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv); - EncryptionUtils.encryptFile(targetContext, file, encryptorCipher); + EncryptionUtils.encryptFile(user.getAccountName(), file, encryptorCipher); String encryptorCipherAuthTag = EncryptionUtils.getAuthenticationTag(encryptorCipher); // Decryption diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 9a86353ff0c4..260524248c30 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -341,10 +341,8 @@ public OCFile saveFileWithParent(OCFile ocFile, Context context) { return ocFile; } - private static final String tempEncryptedFolderPath = "temp_encrypted_folder"; - - public static void clearTempEncryptedFolder(Context context) { - File tempEncryptedFolder = getTempEncryptedFolder(context); + public static void clearTempEncryptedFolder(String accountName) { + File tempEncryptedFolder = new File(FileStorageUtils.getTemporalEncryptedFolderPath(accountName)); if (!tempEncryptedFolder.exists()) { Log_OC.d(TAG,"tempEncryptedFolder not exists"); @@ -360,13 +358,8 @@ public static void clearTempEncryptedFolder(Context context) { } } - public static File getTempEncryptedFolder(Context context) { - String dirPath = context.getFilesDir().getAbsolutePath() + File.separator + tempEncryptedFolderPath; - return new File(dirPath); - } - - public static File createTempEncryptedFolder(Context context) { - File tempEncryptedFolder = getTempEncryptedFolder(context); + public static File createTempEncryptedFolder(String accountName) { + File tempEncryptedFolder = new File(FileStorageUtils.getTemporalEncryptedFolderPath(accountName)); if (!tempEncryptedFolder.exists()) { boolean isTempEncryptedFolderCreated = tempEncryptedFolder.mkdirs(); diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 1e805c244e6d..18de79ad31df 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -553,7 +553,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare byte[] iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength); Cipher cipher = EncryptionUtils.getCipher(Cipher.ENCRYPT_MODE, key, iv); File file = new File(mFile.getStoragePath()); - EncryptedFile encryptedFile = EncryptionUtils.encryptFile(getContext(), file, cipher); + EncryptedFile encryptedFile = EncryptionUtils.encryptFile(user.getAccountName(), file, cipher); // new random file name, check if it exists in metadata String encryptedFileName = EncryptionUtils.generateUid(); diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java index ab27688bd570..2ee4e4e20576 100755 --- a/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java @@ -54,8 +54,6 @@ import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.theme.ViewThemeUtils; -import org.apache.commons.io.FileUtils; - import java.io.File; import java.util.Arrays; import java.util.Optional; @@ -143,7 +141,7 @@ private void showFailedPopupMenu(HeaderViewHolder headerViewHolder) { if (itemId == R.id.action_upload_list_failed_clear) { uploadsStorageManager.clearFailedButNotDelayedUploads(); - FileDataStorageManager.clearTempEncryptedFolder(MainApp.getAppContext()); + clearTempEncryptedFolder(); loadUploadItemsFromDb(); } else if (itemId == R.id.action_upload_list_failed_retry) { @@ -174,8 +172,7 @@ private void showCancelledPopupMenu(HeaderViewHolder headerViewHolder) { if (itemId == R.id.action_upload_list_cancelled_clear) { uploadsStorageManager.clearCancelledUploadsForCurrentAccount(); loadUploadItemsFromDb(); - - FileDataStorageManager.clearTempEncryptedFolder(parentActivity); + clearTempEncryptedFolder(); } else if (itemId == R.id.action_upload_list_cancelled_resume) { retryCancelledUploads(); } @@ -186,6 +183,11 @@ private void showCancelledPopupMenu(HeaderViewHolder headerViewHolder) { popup.show(); } + private void clearTempEncryptedFolder() { + Optional user = parentActivity.getUser(); + user.ifPresent(value -> FileDataStorageManager.clearTempEncryptedFolder(value.getAccountName())); + } + // FIXME For e2e resume is not working private void retryCancelledUploads() { new Thread(() -> { diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index 0a10af4f8033..1ca499e0776a 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -547,8 +547,8 @@ public static byte[] decodeStringToBase64Bytes(String string) { return Base64.decode(string, Base64.NO_WRAP); } - public static EncryptedFile encryptFile(Context context, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { - File tempEncryptedFolder = FileDataStorageManager.createTempEncryptedFolder(context); + public static EncryptedFile encryptFile(String accountName, File file, Cipher cipher) throws InvalidParameterSpecException, IOException { + File tempEncryptedFolder = FileDataStorageManager.createTempEncryptedFolder(accountName); File tempEncryptedFile = File.createTempFile(file.getName(), null, tempEncryptedFolder); encryptFileWithGivenCipher(file, tempEncryptedFile, cipher); String authenticationTagString = getAuthenticationTag(cipher); diff --git a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java index 878784b8edbf..630a1e3def90 100644 --- a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java @@ -106,6 +106,17 @@ public static String getTemporalPath(String accountName) { // that can be in the accountName since 0.1.190B } + public static String getTemporalEncryptedFolderPath(String accountName) { + return MainApp + .getAppContext() + .getFilesDir() + .getAbsolutePath() + + File.separator + + accountName + + File.separator + + "temp_encrypted_folder"; + } + /** * Get absolute path to tmp folder inside app folder for given accountName. */ From 5f1b87fdc06dd2227d442a138feacd11f4cf3354 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sun, 14 Apr 2024 02:41:31 +0000 Subject: [PATCH 019/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-da/strings.xml | 7 +++++++ app/src/main/res/values-zh-rHK/strings.xml | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 0b2cce94bdef..f71abf8e69fe 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -47,6 +47,7 @@ Planlagt Fuldført Opgaven er oprettet + En fejl opstod under sletning af opgaven Opgaven er slettet Slet opgave Assistent @@ -354,6 +355,7 @@ Intet er delt endnu Ingen resultater fundet for din forespørgsel mappe + LIVE Indlæser... Ingen app er sat op til at håndtere denne filtype. sekunder siden @@ -592,6 +594,7 @@ Udvikling Generel Mere + Daglig backup af din kalender og kontakter Daglig backup af dine kontakter Uventet fejl under opsætning af DAVx5 (tidligere kendt som DAVdroid) End-to-end kryptering er blevet konfigureret! @@ -665,6 +668,7 @@ Enheds legitimationsoplysninger er sat op Lokal kopi kunne ikke omdøbes, prøv et andet navn Omdøbning ikke mulig, navnet eksisterer Anmodning om sletning af konto + Anmod om sletning Gendeling er ikke tilladt Videredeling ikke tilladt Intet skaleret billede tilgængeligt. Hent fuldt billede? @@ -685,9 +689,11 @@ Enheds legitimationsoplysninger er sat op Alle dine konti på et sted Automatisk upload + for dine billeder og videoer Kalender og kontakter Synkronisér med DAVx5 Fejl ved indhenting af søgeresultater + Sikker deling er ikke sat op for denne bruger Vælg alle Indstil mediemappe Vælg venligst en skabelon @@ -800,6 +806,7 @@ Enheds legitimationsoplysninger er sat op \"%1$s\" er blevet delt med dig %1$s delte \"%2$s\" med dig Kun billeder + Billeder og videoer Kun videoer Foreslå Konflikter fundet diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 439093a931b7..612b54311747 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -45,6 +45,7 @@ 任務清單加載中,請稍候 無可用的工作項目。選取工作項目類型以建立新工作項目。 沒有可用於 %s 任務項目類型的任務項目,您可以從右下角建立新任務項目。 + 進行中 預定 已完成 建立任務項目時發生錯誤 @@ -722,7 +723,7 @@ 使用圖片作為 設定狀態 設定狀態訊息 - 在設置端到端加密期間,您將收到一個隨機的 12 字助記碼,您需要在其他設備上打開文件。這將僅存儲在此設備上,並且可以在此屏幕中再次顯示。請記在安全的地方! + 在設置端到端加密期間,您將收到一個隨機的 12 字助記碼,您需要在其他設備上打開文件。這將僅存儲在此設備上,並且可以在此螢幕中再次顯示。請記在安全的地方! 分享 分享並複製連結 分享 From f7b883c9363dbcf6805ea9e761db6fc47fa90d32 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Mon, 15 Apr 2024 02:38:53 +0000 Subject: [PATCH 020/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-fr/strings.xml | 136 +++++++++--------- .../android/fr-FR/full_description.txt | 30 ++-- 2 files changed, 82 insertions(+), 84 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ae580052e56a..363fa1ee4dc9 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -14,9 +14,9 @@ Envoyer / Partager Affichage mosaïque Affichage liste - Restore contacts and calendar + Restaurer les contacts et l’agenda Nouveau dossier - Move or Copy + Déplacer ou copier Ouvrir avec Rechercher Propriétés @@ -37,23 +37,23 @@ Autoriser le repartage Affiche un widget du tableau de bord Recherche dans %s - All - Type some text - Are you sure you want to delete this task? - Delete Task + Tout + Tapez du texte + Êtes-vous sûr de vouloir supprimer cette tâche ? + Supprimer la tâche Échec - Task List are loading, please wait - No task available. Select a task type to create a new task. - No task available for %s task type, you can create a new task from bottom right. + La liste des tâches charge, veuillez patienter + Aucune tâche disponible. Sélectionner un type de tâche pour créer une nouvelle tâche. + Aucune tâche disponible pour le type de tâche %s, vous pouvez créer une nouvelle tâche en bas à droite. En cours Planifié Terminé - An error occurred while creating the task - Task successfully created + Une erreur est survenue lors de la création de la tâche + La tâche a bien été créée Une erreur est survenue lors de la suppression de la tâche Tâche supprimée avec succès Impossible de récupérer la liste des tâches, veuillez vérifier votre connexion Internet. - Delete Task + Supprimer la tâche Impossible de récupérer les types des tâches, veuillez vérifier votre connexion Internet. Assistant Inconnu @@ -95,11 +95,11 @@ Définir un dossier personnalisé Désactiver l\'économie de batterie Masquer le dossier - Preparing auto upload + Préparation du téléversement automatique Avatar Absent Paramètres de sauvegarde - Contacts and calendar backup + Sauvegarder les contacts et l’agenda Fermer Désactiver L\'optimisation de la batterie est peut-être active sur votre appareil. Le téléversement automatique ne fonctionne correctement que si vous excluez cette application de l\'optimisation. @@ -177,7 +177,7 @@ Si vous sélectionnez les deux versions, le fichier local aura un numéro ajouté à son nom. Fichier serveur Sauvegarde des contacts - Contact permission is required. + La permission d’accès à vos contacts est requise L\'icône de l\'utilisateur pour la liste des contacts Pas de permission donnée, rien n\'a été importé. Contacts @@ -246,10 +246,10 @@ Réception en cours… %1$s reçu Reçu - Certain files were canceled during the download by user - Error occurred while downloading files + Certains fichiers ont été annulés pendant le téléchargement par l’utilisateur + Une erreur est survenue lors du téléchargement des fichiers Pas encore téléchargé - Unexpected error occurred while downloading files + Erreur inattendue survenue lors du téléchargement des fichiers Fermer le panneau latéral Communauté Image d’arrière-plan de l’en-tête du menu-tiroir @@ -262,7 +262,7 @@ Accueil Notifications Sur l’appareil - Personal files + Fichiers personnels Modifiés récemment Partagé Fichiers supprimés @@ -281,7 +281,7 @@ Plus d’applications Nextcloud Nextcloud Notes Nextcloud Talk - Failed to pick email address. + Le choix de l’adresse électronique a échoué. Définir comme chiffré Configurer le chiffrement Décryptage… @@ -316,8 +316,7 @@ Erreur au démarrage de l\'appareil photo Erreur lors de la numérisation du document Comptes - Times run in 48h - Created + Créée Nom de la tâche Progression État @@ -367,7 +366,7 @@ Aucun partage Aucun résultat trouvé pour votre requête dossier - LIVE + EN DIRECT Chargement… Aucune application trouvée pour ce type de fichier. à l’instant @@ -412,16 +411,16 @@ Le nom du fichier contient au moins un caractère invalide Nom du fichier Sécurisez et contrôlez vos données - Secure collaboration and file exchange - Easy-to-use webmail, calendar and contacts - Screensharing, online meetings and web conferences + Collaboration et échange de fichiers sécurisés + Messagerie web, agenda, contacts faciles à utiliser + Partage d’écran, réunions en ligne et conférences en ligne Le dossier existe déjà Créer Aucun dossier Choisir - Choose target folder - Copy - Move + Sélectionner le dossier cible + Copier + Déplacer Vous n\'avez pas la permission %s de copier ce fichier de créer ce fichier @@ -436,7 +435,7 @@ Tous les fichiers ont été déplacés Suivant 4 heures - This icon indicates availability of live photo + Cette icône indique la disponibilité de live photo Le nom résultera en un fichier caché Nom Note @@ -602,16 +601,16 @@ Renommer la nouvelle version Que faire si le fichier existe déjà ? Ajouter un compte - Sync calendar and contacts + Synchroniser l’agenda et les contacts Ni Google Play Store ou F-Droid ne sont installés Configurer DAVx5 (autrefois connu comme DAVdroid) (v1.3.0+) pour le compte actuel - Calendar and contacts sync set up + La synchronisation de l\'agenda et des contacts a bien été configurée. À propos Préférences Dév Général Plus - Daily backup of your calendar and contacts + Sauvegarde quotidienne de votre agenda et des contacts Sauvegarde quotidienne de vos contacts Erreur inattendue lors de la configuration de DAVx5 (anciennement connu sous le nom de DAVdroid) Le chiffrement de bout en bout est configuré ! @@ -624,8 +623,8 @@ Mentions Le fichier original sera… Le fichier original sera… - Exclude hidden files and folders - Exclude hidden + Exclure les fichiers et dossiers cachés + Exclure les cachés Stockage dans des sous-dossiers se basant sur la date Utiliser des sous-dossiers Options du sous-dossier @@ -674,17 +673,17 @@ Vous pouvez retirer le chiffrement de bout en bout localement sur ce client Vous pouvez retirer le chiffrement de bout en bout localement sur ce client. Les fichiers chiffrés resteront sur le serveur, mais ne seront plus synchronisés avec cet ordinateur. Échec de la suppression - Remove local account - Remove account from device and delete all local files + Supprimer le compte local + Supprimer le compte de l\'appareil et supprimer tous les fichiers locaux Erreur lors de la suppression des notifications. Supprimer Supprimé Entrez un nouveau nom Impossible de renommer la version locale; veuillez réessayer avec un nom différent Impossible de renommer, le nom est déjà utilisé - Request account deletion - Request deletion - Request permanent deletion of account by service provider + Demander la suppression du compte + Demander la suppression + Demander la suppression permanente du compte par le fournisseur de services Le repartage n\'est pas autorisé Le repartage est interdit Aucune image réduite disponible. Télécharger l\'image originale ? @@ -705,12 +704,12 @@ Tous vos comptes en un seul endroit Téléversement automatique - for your photos and videos - Calendar and contacts + pour vos photos et vidéos + Agenda et contacts Synchroniser avec DAVx5 Erreur lors de l\'obtention des résultats de recherche - Secure sharing is not set up for this user - Secure share … + Le partage sécurité n’est pas configuré pour cet utilisateur + Partage sécurisé… Tout sélectionner Paramétrer le dossier média Veuillez sélectionner un modèle @@ -725,7 +724,7 @@ Enregistrer le message d\'état Pendant la configuration du chiffrement de bout en bout, vous recevrez une phrase secrète aléatoire de 12 mots dont vous aurez besoin pour ouvrir vos fichiers sur d\'autres appareils. Cette phrase secrète ne sera stockée que sur cet appareil, et pourra être affichée à nouveau sur cet écran. Veuillez la noter en lieu sûr ! Partager - Share and Copy Link + Partager et copier le lien Partage %1$s Expire le %1$s @@ -745,7 +744,7 @@ Partager le lien (%1$s) Définir une date d\'expiration Définir un mot de passe - Resharing is not allowed during secure file drop + Le repartage n’est pas autorisé pendant le dépôt d’un fichier sécurisé Protégé par mot de passe Peut modifier Dépôt de fichier @@ -769,7 +768,6 @@ partagé par lien Partagé avec vous par %1$s L\'ajout du partage a échoué - Adding share failed. This file or folder has already been shared with this person or group. Afficher les photos Afficher les vidéos Se connecter avec un fournisseur @@ -812,7 +810,7 @@ Accès complet Média en lecture seule Images - The self-hosted productivity platform that keeps you in control.\n\nFeatures:\n* Easy, modern interface, suited to the theme of your server\n* Upload files to your Nextcloud server\n* Share them with others\n* Keep your favorite files and folders synced\n* Search across all folders on your server\n* Auto Upload for photos and videos taken by your device\n* Keep up to date with notifications\n* Multi-account support\n* Secure access to your data with fingerprint or PIN\n* Integration with DAVx5 (formerly known as DAVdroid) for easy setup of calendar and contacts synchronization\n\nPlease report all issues at https://github.com/nextcloud/android/issues and discuss this app at https://help.nextcloud.com/c/clients/android\n\nNew to Nextcloud? Nextcloud is a private file sync and share and communication server. It is libre software, and you can host it yourself or pay a company to do it for you. That way, you are in control of your photos, your calendar and contact data, your documents and everything else.\n\nCheck out Nextcloud at https://nextcloud.com + La plateforme de productivité auto-hébergée qui vous redonne le contrôle.\n\nFonctionnalités: \n* Intuitif, interface moderne, adaptée au thème de votre serveur.\n* Envoyez des fichiers sur votre serveur Nextcloud\n* Partagez avec d\'autres personnes\n* Gardez vos fichiers et dossiers préférés synchronisés\n* Recherchez dans tous les dossiers de votre serveur\n* Téléversement automatique des photos et vidéos prises par votre appareil\n* Restez à jour avec les notifications\n* Supporte plusieurs comptes simultanément\n* Accès sécurisé avec votre empreinte digitale ou un PIN\n* Intégration avec DAVx5 (ancien nom : DAVdroid) pour configurer facilement l\'agenda&et synchroniser les contacts\n\nMerci de signaler les problèmes sur https://github.com/nextcloud/android/issues et discutez de cette application sur https://help.nextcloud.com/c/clients/android\n\nNew sur Nextcloud ? Nextcloud est un serveur privé de synchronisation de fichiers&de partage et de communications. C\'est un logiciel libre, et vous pouvez l\'héberger vous-même ou payer une entreprise pour le faire à votre place. De cette façon, vous avez le contrôle de vos photos, votre agenda et vos données de contacts, vos documents et tout le reste.\n\nApprenez en plus sur Nextcloud sur https://nextcloud.com La plateforme de productivité auto-hébergée qui vous permet de garder le contrôle.\nCeci est la version officielle de développement, qui présente chaque jour quelques-unes des fonctionnalités non-testées les plus récentes, causant parfois des instabilités ou des pertes de données. Cette application s\'adresse aux utilisateurs volontaires souhaitant tester et rapporter les problèmes qui peuvent arriver. Ne l\'utilisez jamais pour un environnement de production!\n\nLes versions officielles et en développement sont disponibles sur F-droid, et peuvent être utilisées en même temps. La plateforme de productivité auto-hébergée qui vous permet de garder le contrôle La plateforme de productivité auto-hébergée qui vous permet de garder le contrôle (version de développement en démonstration) @@ -826,7 +824,7 @@ \"%1$s\" a été partagé avec vous %1$s a partagé \"%2$s\" avec vous Photos uniquement - Photos and videos + Photos et vidéos Vidéos uniquement Suggérer Des conflits ont été trouvés @@ -868,7 +866,7 @@ Les fichiers supprimés s\'afficheront ici et vous pourrez les restaurer. Le fichier %1$s n\'a pas pu être supprimé ! Le fichier %1$s n\'a pas pu être restauré ! - Delete permanently + Supprimer définitivement Le chargement de la corbeille a échoué ! Des fichiers n\'ont pas pu être supprimés de manière définitive ! Déverrouiller le fichier @@ -884,13 +882,13 @@ Impossible de mettre à jour. Vérifiez que le fichier existe de modifier ce partage La mise à jour du partage a échoué - Clear cancelled uploads - Resume cancelled uploads - Clear failed uploads - Retry failed uploads - Some files not exists those files cannot be resumed - Pause all uploads - Resume all uploads + Effacer les téléversements annulés + Poursuivre les téléversements annulés + Effacer les téléversements échoués + Relancer les envois en erreur + Certains fichiers n’existent pas et ne peuvent pas être relancés. + Suspendre tous les téléversements + Poursuivre tous les téléversements Impossible de créer le fichier local Téléverser depuis… Téléverser du contenu à partir d\'autres applications @@ -902,7 +900,7 @@ Extrait du fichier texte (.txt) Spécifiez le nom et le type du fichier à téléverser Téléverser des fichiers - All uploads are paused + Tous les téléversements sont suspendus Bouton d\'action d\'upload Supprimer Aucun téléversement disponible @@ -911,10 +909,10 @@ Stockage local plein Le fichier n\'a pas pu être copié sur le stockage local Impossible de verrouiller le dossier - Upload was cancelled by user + Le téléversement a été annulé par l\'utilisateur Le chiffrement n\'est disponible que pour les versions d\'Android>= 5.0 Il n\'y a pas assez d\'espace pour copier les fichiers sélectionnés dans le dossier %1$s. Souhaitez-vous plutôt les déplacer ? - Storage quota exceeded + Quota de stockage dépassé Numériser un document depuis l\'appareil photo Conflit de synchronisation, veuillez le résoudre manuellement Erreur inconnue @@ -926,10 +924,10 @@ Le fichier à téléverser n\'a pas été trouvé. Merci de vérifier si ce fichier existe. le fichier ne peut être téléchargé Aucun fichier à téléverser - File not found. Are you sure that this file exists or has a previous conflict not been resolved? - We couldnt locate the file on server. Another user may have deleted the file + Fichier non trouvé. Êtes-vous sûr que ce fichier existe ou qu\'un conflit précédent n\'a pas été résolu ? + Impossible de retrouver le fichier sur le serveur. Un autre utilisateur l\'a peut-être supprimé Nom du dossier - Retry to upload failed local files + Réessayer de téléverser les fichiers locaux ayant échoués Sélectionnez le dossier de téléversement Impossible d\'envoyer %1$s Le téléversement a échoué, reconnectez-vous @@ -953,7 +951,7 @@ En cours Échec / En attente de reprise Envoyé - Cancelled + Annulé En attente de téléversement Téléversements Annulé @@ -968,7 +966,7 @@ Récupération de la version serveur … L\'application s\'est arrêtée Terminé - Same file found on remote, skipping upload + Le même fichier a été trouvé sur le serveur distant, le téléversement est ignoré Erreur inconnue Un virus a été détecté. Le téléversement ne peut donc pas être réalisé ! En attente de sortie du mode d’économie d’énergie @@ -989,16 +987,16 @@ Veuillez patienter… Vérification des identifiants enregistrés Copie du fichier depuis le stockage privé - Please update the Android System WebView app for a login - Update - Update Android System WebView + Veuillez mettre à jour l\'application Android System WebView pour vous connecter + Mise à jour + Mettre à jour Android System WebView Image quoi de neuf Ignorer Nouveautés dans %1$s Quel est votre statut ? Les widgets ne sont disponibles que sur %1$s 25 ou plus tard Non disponible - Downloading files… + Réception de fichiers… Envoyer un courriel Le dossier de stockage des données n\'existe pas ! Cela peut être dû à une restauration de sauvegarde sur un autre appareil. Retour aux valeurs par défaut. Veuillez vérifier les paramètres pour ajuster le chemin de stockage. diff --git a/src/generic/fastlane/metadata/android/fr-FR/full_description.txt b/src/generic/fastlane/metadata/android/fr-FR/full_description.txt index 24ba78ea975d..1cd11c9e8254 100644 --- a/src/generic/fastlane/metadata/android/fr-FR/full_description.txt +++ b/src/generic/fastlane/metadata/android/fr-FR/full_description.txt @@ -1,19 +1,19 @@ -The self-hosted productivity platform that keeps you in control. +La plateforme de productivité auto-hébergée qui vous redonne le contrôle. -Features: -* Easy, modern interface, suited to the theme of your server -* Upload files to your Nextcloud server -* Share them with others -* Keep your favorite files and folders synced -* Search across all folders on your server -* Auto Upload for photos and videos taken by your device -* Keep up to date with notifications -* Multi-account support -* Secure access to your data with fingerprint or PIN -* Integration with DAVx5 (formerly known as DAVdroid) for easy setup of calendar and contacts synchronization +Fonctionnalités: +* Intuitif, interface moderne, adaptée au thème de votre serveur. +* Envoyez des fichiers sur votre serveur Nextcloud +* Partagez avec d'autres personnes +* Gardez vos fichiers et dossiers préférés synchronisés +* Recherchez dans tous les dossiers de votre serveur +* Téléversement automatique des photos et vidéos prises par votre appareil +* Restez à jour avec les notifications +* Supporte plusieurs comptes simultanément +* Accès sécurisé avec votre empreinte digitale ou un PIN +* Intégration avec DAVx5 (ancien nom : DAVdroid) pour configurer facilement l'agenda&et synchroniser les contacts -Please report all issues at https://github.com/nextcloud/android/issues and discuss this app at https://help.nextcloud.com/c/clients/android +Merci de signaler les problèmes sur https://github.com/nextcloud/android/issues et discutez de cette application sur https://help.nextcloud.com/c/clients/android -New to Nextcloud? Nextcloud is a private file sync and share and communication server. It is libre software, and you can host it yourself or pay a company to do it for you. That way, you are in control of your photos, your calendar and contact data, your documents and everything else. +New sur Nextcloud ? Nextcloud est un serveur privé de synchronisation de fichiers&de partage et de communications. C'est un logiciel libre, et vous pouvez l'héberger vous-même ou payer une entreprise pour le faire à votre place. De cette façon, vous avez le contrôle de vos photos, votre agenda et vos données de contacts, vos documents et tout le reste. -Check out Nextcloud at https://nextcloud.com \ No newline at end of file +Apprenez en plus sur Nextcloud sur https://nextcloud.com \ No newline at end of file From 3bcd2b3703ce6a4a9c2577904f4c44bacd14c660 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 9 Apr 2024 14:25:57 +0200 Subject: [PATCH 021/114] Dont use null path Signed-off-by: alperozturk --- app/src/main/java/com/owncloud/android/datamodel/OCFile.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java index 48108dc91f45..d294f9c0e703 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -265,6 +265,11 @@ public String getDecryptedRemotePath() { } if (isFolder()) { + if (decryptedRemotePath.equals("/null/")) { + Log_OC.d(TAG, "Null folder path found"); + return remotePath; + } + if (decryptedRemotePath.endsWith(PATH_SEPARATOR)) { return decryptedRemotePath; } else { From d9d9cf56b27db0f1e912513490ad5337deddcc5c Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 09:37:16 +0200 Subject: [PATCH 022/114] Check existence of decryptedRemotePath Signed-off-by: alperozturk --- .../operations/RefreshFolderOperation.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 8223c22a9f7e..691f09fb55b8 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -553,6 +553,7 @@ private void synchronizeData(List folderAndFiles) { updatedFiles.add(updatedFile); } + // save updated contents in local database // update file name for encrypted files if (e2EVersion == E2EVersion.V1_2) { @@ -636,20 +637,35 @@ public static void updateFileNameForEncryptedFile(FileDataStorageManager storage mimetype = MimeType.DIRECTORY; } else { DecryptedFile decryptedFile = metadata.getMetadata().getFiles().get(updatedFile.getFileName()); + + if (decryptedFile == null) { + throw new NullPointerException("decryptedFile cannot be null"); + } + decryptedFileName = decryptedFile.getFilename(); mimetype = decryptedFile.getMimetype(); } OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); - String decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; + + if (parentFile == null) { + throw new NullPointerException("parentFile cannot be null"); + } + + String decryptedRemotePath; + if (decryptedFileName != null) { + decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; + } else { + decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName(); + } if (updatedFile.isFolder()) { decryptedRemotePath += "/"; } updatedFile.setDecryptedRemotePath(decryptedRemotePath); - if (mimetype == null || mimetype.isEmpty()) { + if (mimetype.isEmpty()) { if (updatedFile.isFolder()) { updatedFile.setMimeType(MimeType.DIRECTORY); } else { From 82c1c25a2f9afc2aab023a022d7c0e8c2a816dbc Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 11:59:55 +0200 Subject: [PATCH 023/114] Use encrypted remote path for file conflict resolver dialog Signed-off-by: alperozturk --- .../datamodel/FileDataStorageManager.java | 42 +++++++++++++++++++ .../operations/RefreshFolderOperation.java | 1 + .../ui/activity/ConflictsResolveActivity.kt | 13 +++++- .../ui/activity/FileDisplayActivity.java | 21 ++++++---- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 6245958506ad..175c2c2f7c22 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -66,11 +66,14 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import kotlin.Pair; public class FileDataStorageManager { private static final String TAG = FileDataStorageManager.class.getSimpleName(); @@ -2297,6 +2300,45 @@ public void deleteAllFiles() { } } + public String getFolderName(String path) { + return "/" + path.split("/")[1] + "/"; + } + + public String getEncryptedRemotePath(String decryptedRemotePath) { + String folderName = getFolderName(decryptedRemotePath); + + if (folderName == null) { + throw new NullPointerException("folderName cannot be null"); + } + + OCFile folder = getFileByDecryptedRemotePath(folderName); + List files = getAllFilesRecursivelyInsideFolder(folder); + List> decryptedFileNamesAndEncryptedRemotePaths = getDecryptedFileNamesAndEncryptedRemotePaths(files); + + String decryptedFileName = decryptedRemotePath.substring( decryptedRemotePath.lastIndexOf('/') + 1); + + for (Pair item : decryptedFileNamesAndEncryptedRemotePaths) { + if (item.getFirst().equals(decryptedFileName)) { + return item.getSecond(); + } + } + + return null; + } + + private List> getDecryptedFileNamesAndEncryptedRemotePaths(List fileList) { + List> result = new ArrayList<>(); + + for (OCFile file : fileList) { + if (file.isEncrypted()) { + Pair fileNameAndEncryptedRemotePath = new Pair<>(file.getDecryptedFileName(), file.getRemotePath()); + result.add(fileNameAndEncryptedRemotePath); + } + } + + return result; + } + public void removeLocalFiles(User user, FileDataStorageManager storageManager) { File tempDir = new File(FileStorageUtils.getTemporalPath(user.getAccountName())); File saveDir = new File(FileStorageUtils.getSavePath(user.getAccountName())); diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 691f09fb55b8..f5778685d810 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -625,6 +625,7 @@ public static void updateFileNameForEncryptedFileV1(FileDataStorageManager stora } } + // TODO write test for decryptedRemotePath existence... public static void updateFileNameForEncryptedFile(FileDataStorageManager storageManager, @NonNull DecryptedFolderMetadataFile metadata, OCFile updatedFile) { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt index 31a85c9eeb90..3409519384c9 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt @@ -21,6 +21,7 @@ import com.nextcloud.client.jobs.upload.UploadNotificationManager import com.nextcloud.model.HTTPStatusCodes import com.nextcloud.utils.extensions.getParcelableArgument import com.owncloud.android.R +import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.datamodel.OCFile import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.db.OCUpload @@ -42,6 +43,10 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener @Inject var uploadsStorageManager: UploadsStorageManager? = null + @JvmField + @Inject + var fileStorageManager: FileDataStorageManager? = null + private var conflictUploadId: Long = 0 private var existingFile: OCFile? = null private var newFile: OCFile? = null @@ -159,8 +164,12 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener return } if (existingFile == null) { - // fetch info of existing file from server - val operation = ReadFileRemoteOperation(newFile!!.remotePath) + var remotePath = newFile!!.remotePath + if (newFile?.isEncrypted == true) { + remotePath = fileStorageManager?.getEncryptedRemotePath(newFile!!.remotePath) + } + + val operation = ReadFileRemoteOperation(remotePath) @Suppress("TooGenericExceptionCaught") Thread { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index 94a4ed270d13..2c0da6cb52eb 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -54,7 +54,6 @@ import com.nextcloud.client.jobs.download.FileDownloadWorker; import com.nextcloud.client.jobs.upload.FileUploadHelper; import com.nextcloud.client.jobs.upload.FileUploadWorker; -import com.nextcloud.client.jobs.upload.UploadNotificationManager; import com.nextcloud.client.media.PlayerServiceConnection; import com.nextcloud.client.network.ClientFactory; import com.nextcloud.client.network.ConnectivityService; @@ -135,6 +134,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import javax.inject.Inject; @@ -149,6 +149,7 @@ import androidx.fragment.app.FragmentTransaction; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import kotlin.Pair; import kotlin.Unit; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; @@ -878,18 +879,24 @@ private void requestUploadOfFilesFromFileSystem(Intent data, int resultCode) { requestUploadOfFilesFromFileSystem(basePath, filePaths, resultCode); } + private String[] getRemotePaths(String directory, String[] filePaths, String localBasePath) { + String[] remotePaths = new String[filePaths.length]; + for (int j = 0; j < remotePaths.length; j++) { + String relativePath = StringUtils.removePrefix(filePaths[j], localBasePath); + remotePaths[j] = directory + relativePath; + } + + return remotePaths; + } + private void requestUploadOfFilesFromFileSystem(String localBasePath, String[] filePaths, int resultCode) { if (localBasePath != null && filePaths != null) { if (!localBasePath.endsWith("/")) { localBasePath = localBasePath + "/"; } - String[] remotePaths = new String[filePaths.length]; String remotePathBase = getCurrentDir().getRemotePath(); - for (int j = 0; j < remotePaths.length; j++) { - String relativePath = StringUtils.removePrefix(filePaths[j], localBasePath); - remotePaths[j] = remotePathBase + relativePath; - } + String[] decryptedRemotePaths = getRemotePaths(remotePathBase, filePaths, localBasePath); int behaviour = switch (resultCode) { case UploadFilesActivity.RESULT_OK_AND_MOVE -> FileUploadWorker.LOCAL_BEHAVIOUR_MOVE; @@ -899,7 +906,7 @@ private void requestUploadOfFilesFromFileSystem(String localBasePath, String[] f FileUploadHelper.Companion.instance().uploadNewFiles(getUser().orElseThrow(RuntimeException::new), filePaths, - remotePaths, + decryptedRemotePaths, behaviour, true, UploadFileOperation.CREATED_BY_USER, From eaa773d5a994b7d3f3d460adecb116e49fb00879 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 12:05:33 +0200 Subject: [PATCH 024/114] Use better message Signed-off-by: alperozturk --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a2777a201eee..1fb9802c13f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -994,7 +994,7 @@ Thumbnail for new file Thumbnail for existing file Invalid URL - Error creating conflict dialog! + Conflict resolver dialog cannot able to created QR code could not be read! Note icon Add another link From affc77715cb1b8dcdce13e450661e88e1cd40e57 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 12:05:43 +0200 Subject: [PATCH 025/114] Use remote path correctly Signed-off-by: alperozturk --- .../android/ui/activity/ConflictsResolveActivity.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt index 3409519384c9..10315d624c8a 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt @@ -178,7 +178,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener if (result.isSuccess) { existingFile = FileStorageUtils.fillOCFile(result.data[0] as RemoteFile) existingFile?.lastSyncDateForProperties = System.currentTimeMillis() - startDialog() + startDialog(remotePath) } else { Log_OC.e(TAG, "ReadFileRemoteOp returned failure with code: " + result.httpCode) showErrorAndFinish(result.httpCode) @@ -189,11 +189,16 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener } }.start() } else { - startDialog() + var remotePath = existingFile!!.remotePath + if (newFile?.isEncrypted == true) { + remotePath = fileStorageManager?.getEncryptedRemotePath(existingFile!!.remotePath) + } + + startDialog(remotePath) } } - private fun startDialog() { + private fun startDialog(remotePath: String) { val userOptional = user if (!userOptional.isPresent) { Log_OC.e(TAG, "User not present") @@ -206,7 +211,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener if (prev != null) { fragmentTransaction.remove(prev) } - if (existingFile != null && storageManager.fileExists(newFile?.remotePath)) { + if (existingFile != null && storageManager.fileExists(remotePath)) { val dialog = ConflictsResolveDialog.newInstance( existingFile, newFile, From 7c15334dc0bf697270924c4ab00401a8a0b60e59 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 12:07:56 +0200 Subject: [PATCH 026/114] Remove unused imports and logic Signed-off-by: alperozturk --- .../owncloud/android/datamodel/FileDataStorageManager.java | 2 -- app/src/main/java/com/owncloud/android/datamodel/OCFile.java | 5 ----- .../owncloud/android/ui/activity/FileDisplayActivity.java | 2 -- 3 files changed, 9 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 175c2c2f7c22..6026f30d6a0d 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -66,8 +66,6 @@ import java.util.List; import java.util.Locale; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import androidx.annotation.NonNull; import androidx.annotation.Nullable; diff --git a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java index d294f9c0e703..48108dc91f45 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -265,11 +265,6 @@ public String getDecryptedRemotePath() { } if (isFolder()) { - if (decryptedRemotePath.equals("/null/")) { - Log_OC.d(TAG, "Null folder path found"); - return remotePath; - } - if (decryptedRemotePath.endsWith(PATH_SEPARATOR)) { return decryptedRemotePath; } else { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index 2c0da6cb52eb..4e7496dc62ec 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -134,7 +134,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.Optional; import javax.inject.Inject; @@ -149,7 +148,6 @@ import androidx.fragment.app.FragmentTransaction; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import kotlin.Pair; import kotlin.Unit; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; From 7d9a8f1d9fd56d822e83c23f8efaa0110206ff8b Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 12:25:21 +0200 Subject: [PATCH 027/114] Add correct decryptedRemotePath for v1 Signed-off-by: alperozturk --- .../operations/RefreshFolderOperation.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index f5778685d810..f71e52cf43fc 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -585,6 +585,7 @@ public static Object getDecryptedFolderMetadata(boolean encryptedAncestor, return metadata; } + // TODO write test for decryptedRemotePath existence... public static void updateFileNameForEncryptedFileV1(FileDataStorageManager storageManager, @NonNull DecryptedFolderMetadataFileV1 metadata, OCFile updatedFile) { @@ -598,13 +599,28 @@ public static void updateFileNameForEncryptedFileV1(FileDataStorageManager stora } else { com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile decryptedFile = metadata.getFiles().get(updatedFile.getFileName()); + + if (decryptedFile == null) { + throw new NullPointerException("decryptedFile cannot be null"); + } + decryptedFileName = decryptedFile.getEncrypted().getFilename(); mimetype = decryptedFile.getEncrypted().getMimetype(); } OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); - String decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; + + if (parentFile == null) { + throw new NullPointerException("parentFile cannot be null"); + } + + String decryptedRemotePath; + if (decryptedFileName != null) { + decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; + } else { + decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName(); + } if (updatedFile.isFolder()) { decryptedRemotePath += "/"; From 9fd1ef520508a69ddb04e11fcc5f4cf97e692589 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 13:04:12 +0200 Subject: [PATCH 028/114] Add testUpdateFileNameForEncryptedFileWhenEncryptedFileUploadRemotePathShouldSetAsEncrypted Signed-off-by: alperozturk --- .../android/utils/EncryptionUtilsV2IT.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt index b52460e30eb8..06a81e31cf7b 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt @@ -21,11 +21,15 @@ import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile +import com.owncloud.android.lib.resources.status.CapabilityBooleanType +import com.owncloud.android.lib.resources.status.OCCapability +import com.owncloud.android.operations.RefreshFolderOperation import com.owncloud.android.util.EncryptionTestIT import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue import org.junit.Assert.assertNotEquals import org.junit.Test +import java.security.SecureRandom class EncryptionUtilsV2IT : AbstractIT() { private val encryptionTestUtils = EncryptionTestUtils() @@ -781,6 +785,44 @@ class EncryptionUtilsV2IT : AbstractIT() { assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, jsonBase64, certs)) } + @Test + @Throws(Exception::class) + fun testUpdateFileNameForEncryptedFileWhenEncryptedFileUploadRemotePathShouldSetAsEncrypted() { + OCFile("/").apply { + storageManager.saveFile(this) + } + + val folder = OCFile("/TestFolder/").apply { + decryptedRemotePath = "/TestFolder/" + isEncrypted = true + fileLength = SecureRandom().nextLong() + setFolder() + parentId = storageManager.getFileByDecryptedRemotePath("/")!!.fileId + storageManager.saveFile(this) + } + + val imageFile = OCFile("/TestFolder/test_pic.png").apply { + mimeType = "image/png" + fileName = "test_pic.png" + isEncrypted = true + fileLength = 1024000 + modificationTimestamp = 1188206955000 + parentId = storageManager.getFileByEncryptedRemotePath("/TestFolder/").fileId + storageManager.saveFile(this) + } + + val remotePathBeforeUpdate = imageFile.remotePath + + val metadata = EncryptionTestUtils().generateFolderMetadataV2( + client.userId, + EncryptionTestIT.publicKey + ) + + RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder) + + assertNotEquals(remotePathBeforeUpdate, imageFile.remotePath) + } + /** * DecryptedFolderMetadata -> EncryptedFolderMetadata -> JSON -> encrypt -> decrypt -> JSON -> * EncryptedFolderMetadata -> DecryptedFolderMetadata From 182673672fe3bc5338190a5e820c304a38a4f398 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 15:58:54 +0200 Subject: [PATCH 029/114] Add test Signed-off-by: alperozturk --- .../android/utils/EncryptionUtilsV2IT.kt | 36 ++--- .../e2e/v2/decrypted/DecryptedMetadata.kt | 2 +- .../operations/RefreshFolderOperation.java | 135 ++++++++++-------- 3 files changed, 93 insertions(+), 80 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt index 06a81e31cf7b..96cf6f04d3ac 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt @@ -21,8 +21,6 @@ import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile -import com.owncloud.android.lib.resources.status.CapabilityBooleanType -import com.owncloud.android.lib.resources.status.OCCapability import com.owncloud.android.operations.RefreshFolderOperation import com.owncloud.android.util.EncryptionTestIT import junit.framework.TestCase.assertEquals @@ -788,39 +786,43 @@ class EncryptionUtilsV2IT : AbstractIT() { @Test @Throws(Exception::class) fun testUpdateFileNameForEncryptedFileWhenEncryptedFileUploadRemotePathShouldSetAsEncrypted() { - OCFile("/").apply { + val rootPath = "/" + val folderPath = "/TestFolder/" + + OCFile(rootPath).apply { storageManager.saveFile(this) } - val folder = OCFile("/TestFolder/").apply { - decryptedRemotePath = "/TestFolder/" + OCFile(folderPath).apply { + decryptedRemotePath = folderPath isEncrypted = true fileLength = SecureRandom().nextLong() setFolder() - parentId = storageManager.getFileByDecryptedRemotePath("/")!!.fileId + parentId = storageManager.getFileByDecryptedRemotePath(rootPath)!!.fileId storageManager.saveFile(this) } - val imageFile = OCFile("/TestFolder/test_pic.png").apply { + val decryptedFilename = "image.png" + val mockEncryptedFilename = "encrypted_file_name.png" + + val imageFile = OCFile(folderPath + decryptedFilename).apply { mimeType = "image/png" - fileName = "test_pic.png" + fileName = mockEncryptedFilename isEncrypted = true fileLength = 1024000 modificationTimestamp = 1188206955000 - parentId = storageManager.getFileByEncryptedRemotePath("/TestFolder/").fileId + parentId = storageManager.getFileByEncryptedRemotePath(folderPath).fileId storageManager.saveFile(this) } - val remotePathBeforeUpdate = imageFile.remotePath - - val metadata = EncryptionTestUtils().generateFolderMetadataV2( - client.userId, - EncryptionTestIT.publicKey - ) + val decryptedMetadata = DecryptedMetadata().apply { + folders = mutableMapOf(mockEncryptedFilename to decryptedFilename) + } + val metadata = DecryptedFolderMetadataFile(decryptedMetadata) - RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder) + RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, imageFile) - assertNotEquals(remotePathBeforeUpdate, imageFile.remotePath) + assertNotEquals(decryptedFilename, imageFile.fileName) } /** diff --git a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt index 88099b6702b6..f27cd440bb5a 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt +++ b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt @@ -13,7 +13,7 @@ data class DecryptedMetadata( val keyChecksums: MutableList = mutableListOf(), val deleted: Boolean = false, var counter: Long = 0, - val folders: MutableMap = mutableMapOf(), + var folders: MutableMap = mutableMapOf(), val files: MutableMap = mutableMapOf(), @Transient var metadataKey: ByteArray = EncryptionUtils.generateKey() diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index f71e52cf43fc..e4a8d506f7de 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -62,11 +62,9 @@ import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; /** - * Remote operation performing the synchronization of the list of files contained in a folder identified with its - * remote path. - * Fetches the list and properties of the files contained in the given folder, including their properties, and updates - * the local database with them. - * Does NOT enter in the child folders to synchronize their contents also. + * Remote operation performing the synchronization of the list of files contained in a folder identified with its remote + * path. Fetches the list and properties of the files contained in the given folder, including their properties, and + * updates the local database with them. Does NOT enter in the child folders to synchronize their contents also. */ @SuppressWarnings("PMD.AvoidDuplicateLiterals") public class RefreshFolderOperation extends RemoteOperation { @@ -74,37 +72,53 @@ public class RefreshFolderOperation extends RemoteOperation { private static final String TAG = RefreshFolderOperation.class.getSimpleName(); public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED = - RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED"; + RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED"; public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED = - RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED"; + RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED"; - /** Time stamp for the synchronization process in progress */ + /** + * Time stamp for the synchronization process in progress + */ private long mCurrentSyncTime; - /** Remote folder to synchronize */ + /** + * Remote folder to synchronize + */ private OCFile mLocalFolder; - /** Access to the local database */ + /** + * Access to the local database + */ private FileDataStorageManager mStorageManager; - /** Account where the file to synchronize belongs */ + /** + * Account where the file to synchronize belongs + */ private User user; - /** Android context; necessary to send requests to the download service */ + /** + * Android context; necessary to send requests to the download service + */ private Context mContext; - /** Files and folders contained in the synchronized folder after a successful operation */ + /** + * Files and folders contained in the synchronized folder after a successful operation + */ private List mChildren; - /** Counter of conflicts found between local and remote files */ + /** + * Counter of conflicts found between local and remote files + */ private int mConflictsFound; - /** Counter of failed operations in synchronization of kept-in-sync files */ + /** + * Counter of failed operations in synchronization of kept-in-sync files + */ private int mFailsInKeptInSyncFound; /** - * Map of remote and local paths to files that where locally stored in a location - * out of the ownCloud folder and couldn't be copied automatically into it + * Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and + * couldn't be copied automatically into it **/ private Map mForgottenLocalFiles; @@ -113,10 +127,14 @@ public class RefreshFolderOperation extends RemoteOperation { */ private boolean mSyncFullAccount; - /** 'True' means that the remote folder changed and should be fetched */ + /** + * 'True' means that the remote folder changed and should be fetched + */ private boolean mRemoteFolderChanged; - /** 'True' means that Etag will be ignored */ + /** + * 'True' means that Etag will be ignored + */ private boolean mIgnoreETag; /** @@ -131,16 +149,14 @@ public class RefreshFolderOperation extends RemoteOperation { /** * Creates a new instance of {@link RefreshFolderOperation}. * - * @param folder Folder to synchronize. - * @param currentSyncTime Time stamp for the synchronization process in progress. - * @param syncFullAccount 'True' means that this operation is part of a full account - * synchronization. - * @param ignoreETag 'True' means that the content of the remote folder should - * be fetched and updated even though the 'eTag' did not - * change. - * @param dataStorageManager Interface with the local database. - * @param user ownCloud account where the folder is located. - * @param context Application context. + * @param folder Folder to synchronize. + * @param currentSyncTime Time stamp for the synchronization process in progress. + * @param syncFullAccount 'True' means that this operation is part of a full account synchronization. + * @param ignoreETag 'True' means that the content of the remote folder should be fetched and updated even + * though the 'eTag' did not change. + * @param dataStorageManager Interface with the local database. + * @param user ownCloud account where the folder is located. + * @param context Application context. */ public RefreshFolderOperation(OCFile folder, long currentSyncTime, @@ -196,8 +212,8 @@ public Map getForgottenLocalFiles() { } /** - * Returns the list of files and folders contained in the synchronized folder, - * if called after synchronization is complete. + * Returns the list of files and folders contained in the synchronized folder, if called after synchronization is + * complete. * * @return List of files and folders contained in the synchronized folder. */ @@ -207,7 +223,7 @@ public List getChildren() { /** * Performs the synchronization. - * + *

* {@inheritDoc} */ @Override @@ -246,7 +262,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { if (!mSyncFullAccount && mRemoteFolderChanged) { sendLocalBroadcast( EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result - ); + ); } if (result.isSuccess() && !mSyncFullAccount && !mOnlyFileMetadata) { @@ -256,7 +272,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { if (!mSyncFullAccount) { sendLocalBroadcast( EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result - ); + ); } return result; @@ -371,7 +387,7 @@ private RemoteOperationResult checkForChanges(OwnCloudClient client) { result = new RemoteOperationResult(ResultCode.OK); Log_OC.i(TAG, "Checked " + user.getAccountName() + remotePath + " : " + - (mRemoteFolderChanged ? "changed" : "not changed")); + (mRemoteFolderChanged ? "changed" : "not changed")); } else { // check failed @@ -380,10 +396,10 @@ private RemoteOperationResult checkForChanges(OwnCloudClient client) { } if (result.isException()) { Log_OC.e(TAG, "Checked " + user.getAccountName() + remotePath + " : " + - result.getLogMessage(), result.getException()); + result.getLogMessage(), result.getException()); } else { Log_OC.e(TAG, "Checked " + user.getAccountName() + remotePath + " : " + - result.getLogMessage()); + result.getLogMessage()); } } @@ -425,9 +441,9 @@ private void removeLocalFolder() { /** - * Synchronizes the data retrieved from the server about the contents of the target folder - * with the current data in the local database. - * + * Synchronizes the data retrieved from the server about the contents of the target folder with the current data in + * the local database. + *

* Grants that mChildren is updated with fresh data after execution. * * @param folderAndFiles Remote folder and children files in Folder @@ -641,7 +657,6 @@ public static void updateFileNameForEncryptedFileV1(FileDataStorageManager stora } } - // TODO write test for decryptedRemotePath existence... public static void updateFileNameForEncryptedFile(FileDataStorageManager storageManager, @NonNull DecryptedFolderMetadataFile metadata, OCFile updatedFile) { @@ -663,7 +678,6 @@ public static void updateFileNameForEncryptedFile(FileDataStorageManager storage mimetype = decryptedFile.getMimetype(); } - OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); if (parentFile == null) { @@ -701,8 +715,8 @@ private void setLocalFileDataOnUpdatedFile(OCFile remoteFile, OCFile localFile, updatedFile.setFileId(localFile.getFileId()); updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData()); updatedFile.setModificationTimestampAtLastSyncForData( - localFile.getModificationTimestampAtLastSyncForData() - ); + localFile.getModificationTimestampAtLastSyncForData() + ); if (localFile.isEncrypted()) { if (mLocalFolder.getStoragePath() == null) { updatedFile.setStoragePath(FileStorageUtils.getDefaultSavePathFor(user.getAccountName(), mLocalFolder) + @@ -718,7 +732,7 @@ private void setLocalFileDataOnUpdatedFile(OCFile remoteFile, OCFile localFile, // eTag will not be updated unless file CONTENTS are synchronized if (!updatedFile.isFolder() && localFile.isDown() && - !updatedFile.getEtag().equals(localFile.getEtag())) { + !updatedFile.getEtag().equals(localFile.getEtag())) { updatedFile.setEtagInConflict(updatedFile.getEtag()); } @@ -728,8 +742,8 @@ private void setLocalFileDataOnUpdatedFile(OCFile remoteFile, OCFile localFile, updatedFile.setFileLength(remoteFile.getFileLength()); updatedFile.setMountType(remoteFile.getMountType()); } else if (remoteFolderChanged && MimeTypeUtil.isImage(remoteFile) && - remoteFile.getModificationTimestamp() != - localFile.getModificationTimestamp()) { + remoteFile.getModificationTimestamp() != + localFile.getModificationTimestamp()) { updatedFile.setUpdateThumbnailNeeded(true); Log_OC.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server"); } @@ -764,13 +778,12 @@ public static Map prefillLocalFilesMap(Object metadata, List + * If download or upload is needed, request the operation to the corresponding service and goes on. * - * @param filesToSyncContents Synchronization operations to execute. + * @param filesToSyncContents Synchronization operations to execute. */ private void startContentSynchronizations(List filesToSyncContents) { RemoteOperationResult contentsResult; @@ -783,10 +796,10 @@ private void startContentSynchronizations(List filesTo mFailsInKeptInSyncFound++; if (contentsResult.getException() != null) { Log_OC.e(TAG, "Error while synchronizing favourites : " - + contentsResult.getLogMessage(), contentsResult.getException()); + + contentsResult.getLogMessage(), contentsResult.getException()); } else { Log_OC.e(TAG, "Error while synchronizing favourites : " - + contentsResult.getLogMessage()); + + contentsResult.getLogMessage()); } } } // won't let these fails break the synchronization process @@ -796,9 +809,9 @@ private void startContentSynchronizations(List filesTo /** * Syncs the Share resources for the files contained in the folder refreshed (children, not deeper descendants). * - * @param client Handler of a session with an OC server. - * @return The result of the remote operation retrieving the Share resources in the folder refreshed by - * the operation. + * @param client Handler of a session with an OC server. + * @return The result of the remote operation retrieving the Share resources in the folder refreshed by the + * operation. */ private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) { RemoteOperationResult result; @@ -826,12 +839,10 @@ private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) { } /** - * Sends a message to any application component interested in the progress - * of the synchronization. + * Sends a message to any application component interested in the progress of the synchronization. * * @param event broadcast event (Intent Action) - * @param dirRemotePath Remote path of a folder that was just synchronized - * (with or without success) + * @param dirRemotePath Remote path of a folder that was just synchronized (with or without success) * @param result remote operation result */ private void sendLocalBroadcast(String event, String dirRemotePath, RemoteOperationResult result) { From f55d61c05a6b5022e6bcab6eeaea110a44df0e57 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 16:30:27 +0200 Subject: [PATCH 030/114] Add tests Signed-off-by: alperozturk --- .../java/com/owncloud/android/EncryptionIT.kt | 32 +++++++++++++ .../android/utils/EncryptionUtilsIT.kt | 30 +++++++++++- .../android/utils/EncryptionUtilsV2IT.kt | 48 ++++--------------- .../e2e/v2/decrypted/DecryptedMetadata.kt | 2 +- .../operations/RefreshFolderOperation.java | 1 - 5 files changed, 71 insertions(+), 42 deletions(-) create mode 100644 app/src/androidTest/java/com/owncloud/android/EncryptionIT.kt diff --git a/app/src/androidTest/java/com/owncloud/android/EncryptionIT.kt b/app/src/androidTest/java/com/owncloud/android/EncryptionIT.kt new file mode 100644 index 000000000000..ed119a2a9d68 --- /dev/null +++ b/app/src/androidTest/java/com/owncloud/android/EncryptionIT.kt @@ -0,0 +1,32 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Your Name + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android + +import com.owncloud.android.datamodel.OCFile +import java.security.SecureRandom + +open class EncryptionIT : AbstractIT() { + + fun testFolder(): OCFile { + val rootPath = "/" + val folderPath = "/TestFolder/" + + OCFile(rootPath).apply { + storageManager.saveFile(this) + } + + return OCFile(folderPath).apply { + decryptedRemotePath = folderPath + isEncrypted = true + fileLength = SecureRandom().nextLong() + setFolder() + parentId = storageManager.getFileByDecryptedRemotePath(rootPath)!!.fileId + storageManager.saveFile(this) + } + } +} diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsIT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsIT.kt index 55ab2f472b2c..e5b2cf9d0b95 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsIT.kt @@ -7,13 +7,18 @@ */ package com.owncloud.android.utils -import com.owncloud.android.AbstractIT +import com.owncloud.android.EncryptionIT import com.owncloud.android.datamodel.ArbitraryDataProviderImpl +import com.owncloud.android.datamodel.e2e.v1.decrypted.Data +import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile +import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1 +import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedMetadata import com.owncloud.android.lib.resources.e2ee.CsrHelper +import com.owncloud.android.operations.RefreshFolderOperation import org.junit.Assert.assertEquals import org.junit.Test -class EncryptionUtilsIT : AbstractIT() { +class EncryptionUtilsIT : EncryptionIT() { @Throws( java.security.NoSuchAlgorithmException::class, java.io.IOException::class, @@ -30,4 +35,25 @@ class EncryptionUtilsIT : AbstractIT() { assertEquals(key, EncryptionUtils.getPublicKey(user, e2eUser, arbitraryDataProvider)) } + + @Test + @Throws(Exception::class) + fun testUpdateFileNameForEncryptedFileV1() { + val folder = testFolder() + + val decryptedFilename = "image.png" + val mockEncryptedFilename = "encrypted_file_name.png" + + val decryptedMetadata = DecryptedMetadata() + val filesData = DecryptedFile().apply { + encrypted = Data().apply { + filename = decryptedFilename + } + } + val files = mapOf(mockEncryptedFilename to filesData) + val metadata = DecryptedFolderMetadataFileV1(decryptedMetadata, files) + + RefreshFolderOperation.updateFileNameForEncryptedFileV1(storageManager, metadata, folder) + assertEquals(folder.decryptedRemotePath.contains("null"), false) + } } diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt index 96cf6f04d3ac..286700cf0cbe 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt @@ -10,7 +10,7 @@ package com.owncloud.android.utils import com.google.gson.reflect.TypeToken import com.nextcloud.client.account.MockUser import com.nextcloud.common.User -import com.owncloud.android.AbstractIT +import com.owncloud.android.EncryptionIT import com.owncloud.android.datamodel.OCFile import com.owncloud.android.datamodel.e2e.v1.decrypted.Data import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1 @@ -27,9 +27,8 @@ import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue import org.junit.Assert.assertNotEquals import org.junit.Test -import java.security.SecureRandom -class EncryptionUtilsV2IT : AbstractIT() { +class EncryptionUtilsV2IT : EncryptionIT() { private val encryptionTestUtils = EncryptionTestUtils() private val encryptionUtilsV2 = EncryptionUtilsV2() @@ -785,44 +784,17 @@ class EncryptionUtilsV2IT : AbstractIT() { @Test @Throws(Exception::class) - fun testUpdateFileNameForEncryptedFileWhenEncryptedFileUploadRemotePathShouldSetAsEncrypted() { - val rootPath = "/" - val folderPath = "/TestFolder/" + fun testUpdateFileNameForEncryptedFile() { + val folder = testFolder() - OCFile(rootPath).apply { - storageManager.saveFile(this) - } - - OCFile(folderPath).apply { - decryptedRemotePath = folderPath - isEncrypted = true - fileLength = SecureRandom().nextLong() - setFolder() - parentId = storageManager.getFileByDecryptedRemotePath(rootPath)!!.fileId - storageManager.saveFile(this) - } - - val decryptedFilename = "image.png" - val mockEncryptedFilename = "encrypted_file_name.png" - - val imageFile = OCFile(folderPath + decryptedFilename).apply { - mimeType = "image/png" - fileName = mockEncryptedFilename - isEncrypted = true - fileLength = 1024000 - modificationTimestamp = 1188206955000 - parentId = storageManager.getFileByEncryptedRemotePath(folderPath).fileId - storageManager.saveFile(this) - } - - val decryptedMetadata = DecryptedMetadata().apply { - folders = mutableMapOf(mockEncryptedFilename to decryptedFilename) - } - val metadata = DecryptedFolderMetadataFile(decryptedMetadata) + val metadata = EncryptionTestUtils().generateFolderMetadataV2( + client.userId, + EncryptionTestIT.publicKey + ) - RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, imageFile) + RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder) - assertNotEquals(decryptedFilename, imageFile.fileName) + assertEquals(folder.decryptedRemotePath.contains("null"), false) } /** diff --git a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt index f27cd440bb5a..88099b6702b6 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt +++ b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedMetadata.kt @@ -13,7 +13,7 @@ data class DecryptedMetadata( val keyChecksums: MutableList = mutableListOf(), val deleted: Boolean = false, var counter: Long = 0, - var folders: MutableMap = mutableMapOf(), + val folders: MutableMap = mutableMapOf(), val files: MutableMap = mutableMapOf(), @Transient var metadataKey: ByteArray = EncryptionUtils.generateKey() diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index e4a8d506f7de..82f1790f18aa 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -601,7 +601,6 @@ public static Object getDecryptedFolderMetadata(boolean encryptedAncestor, return metadata; } - // TODO write test for decryptedRemotePath existence... public static void updateFileNameForEncryptedFileV1(FileDataStorageManager storageManager, @NonNull DecryptedFolderMetadataFileV1 metadata, OCFile updatedFile) { From 501c6ee2a30730dbb0daf0f0cb08fa9b66b5426d Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 16:37:07 +0200 Subject: [PATCH 031/114] Extract common logic for mimetype and decrypted remote path Signed-off-by: alperozturk --- .../operations/RefreshFolderOperation.java | 87 +++++++------------ 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 82f1790f18aa..b428efc8feb7 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -601,6 +601,36 @@ public static Object getDecryptedFolderMetadata(boolean encryptedAncestor, return metadata; } + private static void setMimeTypeAndDecryptedRemotePath(OCFile updatedFile, FileDataStorageManager storageManager, String decryptedFileName, String mimetype) { + OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); + + if (parentFile == null) { + throw new NullPointerException("parentFile cannot be null"); + } + + String decryptedRemotePath; + if (decryptedFileName != null) { + decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; + } else { + decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName(); + } + + if (updatedFile.isFolder()) { + decryptedRemotePath += "/"; + } + updatedFile.setDecryptedRemotePath(decryptedRemotePath); + + if (mimetype == null || mimetype.isEmpty()) { + if (updatedFile.isFolder()) { + updatedFile.setMimeType(MimeType.DIRECTORY); + } else { + updatedFile.setMimeType("application/octet-stream"); + } + } else { + updatedFile.setMimeType(mimetype); + } + } + public static void updateFileNameForEncryptedFileV1(FileDataStorageManager storageManager, @NonNull DecryptedFolderMetadataFileV1 metadata, OCFile updatedFile) { @@ -623,34 +653,7 @@ public static void updateFileNameForEncryptedFileV1(FileDataStorageManager stora mimetype = decryptedFile.getEncrypted().getMimetype(); } - - OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); - - if (parentFile == null) { - throw new NullPointerException("parentFile cannot be null"); - } - - String decryptedRemotePath; - if (decryptedFileName != null) { - decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; - } else { - decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName(); - } - - if (updatedFile.isFolder()) { - decryptedRemotePath += "/"; - } - updatedFile.setDecryptedRemotePath(decryptedRemotePath); - - if (mimetype == null || mimetype.isEmpty()) { - if (updatedFile.isFolder()) { - updatedFile.setMimeType(MimeType.DIRECTORY); - } else { - updatedFile.setMimeType("application/octet-stream"); - } - } else { - updatedFile.setMimeType(mimetype); - } + setMimeTypeAndDecryptedRemotePath(updatedFile, storageManager, decryptedFileName, mimetype); } catch (NullPointerException e) { Log_OC.e(TAG, "DecryptedMetadata for file " + updatedFile.getFileId() + " not found!"); } @@ -677,33 +680,7 @@ public static void updateFileNameForEncryptedFile(FileDataStorageManager storage mimetype = decryptedFile.getMimetype(); } - OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); - - if (parentFile == null) { - throw new NullPointerException("parentFile cannot be null"); - } - - String decryptedRemotePath; - if (decryptedFileName != null) { - decryptedRemotePath = parentFile.getDecryptedRemotePath() + decryptedFileName; - } else { - decryptedRemotePath = parentFile.getRemotePath() + updatedFile.getFileName(); - } - - if (updatedFile.isFolder()) { - decryptedRemotePath += "/"; - } - updatedFile.setDecryptedRemotePath(decryptedRemotePath); - - if (mimetype.isEmpty()) { - if (updatedFile.isFolder()) { - updatedFile.setMimeType(MimeType.DIRECTORY); - } else { - updatedFile.setMimeType("application/octet-stream"); - } - } else { - updatedFile.setMimeType(mimetype); - } + setMimeTypeAndDecryptedRemotePath(updatedFile, storageManager, decryptedFileName, mimetype); } catch (NullPointerException e) { Log_OC.e(TAG, "DecryptedMetadata for file " + updatedFile.getFileId() + " not found!"); } From 55aed575dfb58e8935b4b414b305910a64556b7a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 10 Apr 2024 16:48:08 +0200 Subject: [PATCH 032/114] Extract common logic retrieving remote path Signed-off-by: alperozturk --- .../android/datamodel/FileDataStorageManager.java | 13 +++++++++++++ .../android/ui/activity/ConflictsResolveActivity.kt | 12 ++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 6026f30d6a0d..bcdf36f2f940 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -2302,6 +2302,19 @@ public String getFolderName(String path) { return "/" + path.split("/")[1] + "/"; } + public String retrieveRemotePathConsideringEncryption(OCFile file) { + if (file == null) { + throw new NullPointerException("file cannot be null"); + } + + String remotePath = file.getRemotePath(); + if (file.isEncrypted()) { + remotePath = getEncryptedRemotePath(file.getRemotePath()); + } + + return remotePath; + } + public String getEncryptedRemotePath(String decryptedRemotePath) { String folderName = getFolderName(decryptedRemotePath); diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt index 10315d624c8a..a83e5c6dd000 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.kt @@ -164,11 +164,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener return } if (existingFile == null) { - var remotePath = newFile!!.remotePath - if (newFile?.isEncrypted == true) { - remotePath = fileStorageManager?.getEncryptedRemotePath(newFile!!.remotePath) - } - + val remotePath = fileStorageManager?.retrieveRemotePathConsideringEncryption(newFile) ?: return val operation = ReadFileRemoteOperation(remotePath) @Suppress("TooGenericExceptionCaught") @@ -189,11 +185,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener } }.start() } else { - var remotePath = existingFile!!.remotePath - if (newFile?.isEncrypted == true) { - remotePath = fileStorageManager?.getEncryptedRemotePath(existingFile!!.remotePath) - } - + val remotePath = fileStorageManager?.retrieveRemotePathConsideringEncryption(existingFile) ?: return startDialog(remotePath) } } From 221e6dddb87c9ae823d7525adddeb0cffe98c6fb Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 11 Apr 2024 09:36:39 +0200 Subject: [PATCH 033/114] Suppress test class Signed-off-by: alperozturk --- .../java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt index 286700cf0cbe..4d72bbda3c01 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt @@ -28,6 +28,7 @@ import junit.framework.TestCase.assertTrue import org.junit.Assert.assertNotEquals import org.junit.Test +@Suppress("TooManyFunctions", "LargeClass") class EncryptionUtilsV2IT : EncryptionIT() { private val encryptionTestUtils = EncryptionTestUtils() private val encryptionUtilsV2 = EncryptionUtilsV2() From 36128c7ee3342b9627961f971be9cec5c3aca25b Mon Sep 17 00:00:00 2001 From: nextcloud-android-bot Date: Mon, 15 Apr 2024 16:30:31 +0000 Subject: [PATCH 034/114] =?UTF-8?q?=F0=9F=94=84=20synced=20local=20'.githu?= =?UTF-8?q?b/workflows/'=20with=20remote=20'config/workflows/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nextcloud-android-bot --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b05056570d7b..e235d5a23cc2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -53,4 +53,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ab2aa5ed7f1b..b14bc5d28447 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 + uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 with: sarif_file: results.sarif From 2a816c7d1932dbf23a8b6df636e549773c6af2e6 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Tue, 26 Mar 2024 14:35:03 +0100 Subject: [PATCH 035/114] Proof of concept for 10x faster check for changed files Signed-off-by: Jonas Mayer --- .../nextcloud/client/jobs/FilesSyncWork.kt | 14 +++--- .../datamodel/FilesystemDataProvider.java | 3 +- .../android/utils/FilesSyncHelper.java | 43 ++++++++++++++++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt index 651c65aa02d9..1ab6f8ce4651 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt @@ -70,7 +70,7 @@ class FilesSyncWork( @Suppress("MagicNumber") private fun updateForegroundWorker(progressPercent: Int, useForegroundWorker: Boolean) { - if (useForegroundWorker) { + if (!useForegroundWorker) { return } @@ -95,6 +95,7 @@ class FilesSyncWork( @Suppress("MagicNumber") override fun doWork(): Result { backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) + Log_OC.d(TAG,"FILESYNC WORKER STARTED") val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false) // If we are in power save mode, better to postpone upload @@ -114,7 +115,9 @@ class FilesSyncWork( // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem val changedFiles = inputData.getStringArray(CHANGED_FILES) + Log_OC.d(TAG,"FILESYNC WORKER CHANGED FILES: "+changedFiles.contentToString()) collectChangedFiles(changedFiles) + Log_OC.d(TAG,"FILESYNC WORKER CHECKED CHANGED FILES") // Create all the providers we'll need val filesystemDataProvider = FilesystemDataProvider(contentResolver) @@ -129,11 +132,7 @@ class FilesSyncWork( (50 + (index.toDouble() / syncedFolders.size.toDouble()) * 50).toInt(), changedFiles.isNullOrEmpty() ) - if (syncedFolder.isEnabled && ( - changedFiles.isNullOrEmpty() || - MediaFolderType.CUSTOM != syncedFolder.type - ) - ) { + if (syncedFolder.isEnabled) { syncFolder( context, resources, @@ -145,6 +144,7 @@ class FilesSyncWork( ) } } + Log_OC.d(TAG,"FILESYNC WORKER ENDED") val result = Result.success() backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result) return result @@ -222,7 +222,7 @@ class FilesSyncWork( needsWifi = syncedFolder.isWifiOnly uploadAction = syncedFolder.uploadAction } - + Log_OC.d(TAG,"FILESYNC SCHEDULE UPLOAD OF FILE") FileUploadHelper.instance().uploadNewFiles( user, localPaths, diff --git a/app/src/main/java/com/owncloud/android/datamodel/FilesystemDataProvider.java b/app/src/main/java/com/owncloud/android/datamodel/FilesystemDataProvider.java index 6e088e721150..aec6fda1bcd0 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FilesystemDataProvider.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FilesystemDataProvider.java @@ -107,6 +107,7 @@ public Set getFilesForUpload(String localPath, String syncedFolderId) { public void storeOrUpdateFileValue(String localPath, long modifiedAt, boolean isFolder, SyncedFolder syncedFolder) { + // takes multiple milliseconds to query data from database (around 75% of execution time) (6ms) FileSystemDataSet data = getFilesystemDataSet(localPath, syncedFolder); int isFolderValue = 0; @@ -145,7 +146,7 @@ public void storeOrUpdateFileValue(String localPath, long modifiedAt, boolean is } } - + // updating data takes multiple milliseconds (around 25% of exec time) (2 ms) int result = contentResolver.update( ProviderMeta.ProviderTableMeta.CONTENT_URI_FILESYSTEM, cv, diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index c68c54329c1f..387595d19fee 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -20,7 +20,6 @@ import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.BackgroundJobManager; import com.nextcloud.client.jobs.upload.FileUploadHelper; -import com.nextcloud.client.jobs.upload.FileUploadWorker; import com.nextcloud.client.network.ConnectivityService; import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FilesystemDataProvider; @@ -40,6 +39,7 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; @@ -78,6 +78,40 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); Path path = Paths.get(syncedFolder.getLocalPath()); + long startTime = System.nanoTime(); + // chick check for changes + long lastCheck = System.currentTimeMillis(); + ArrayList changedFiles = new ArrayList<>(); + FileUtil.walkFileTree(path, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { + File file = path.toFile(); + if (syncedFolder.isExcludeHidden() && file.isHidden()) { + // exclude hidden file or folder + return FileVisitResult.CONTINUE; + } + if (file.lastModified() >= lastCheck){ + changedFiles.add(file); + } + + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) { + return null; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + return FileVisitResult.CONTINUE; + } + }); + Log_OC.d(TAG,"FILESYNC FINISHED QUICK CHECK FILE "+path+" "+(System.nanoTime() - startTime)); + startTime = System.nanoTime(); FileUtil.walkFileTree(path, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { @@ -87,6 +121,8 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; } if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) { + // storeOrUpdateFileValue takes a few millisec + // -> Rest of this file check takes not even 1 millisec. filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(), attrs.lastModifiedTime().toMillis(), file.isDirectory(), syncedFolder); @@ -108,6 +144,8 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) { return FileVisitResult.CONTINUE; } }); + Log_OC.d(TAG,"FILESYNC FINISHED LONG CHECK FILE "+path+" "+(System.nanoTime() - startTime)); + } catch (IOException e) { Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e); } @@ -117,6 +155,7 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) { public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider) { for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { + Log_OC.d(TAG,"FILESYNC CHECK FOLDER "+syncedFolder.getLocalPath()); if (syncedFolder.isEnabled()) { insertAllDBEntriesForSyncedFolder(syncedFolder); } @@ -135,6 +174,7 @@ public static void insertChangedEntries(SyncedFolderProvider syncedFolderProvide filesystemDataProvider.storeOrUpdateFileValue(changedFile, file.lastModified(),file.isDirectory(), syncedFolder); + Log_OC.d(TAG,"FILESYNC ADDED UPLOAD TO DB"); break; } } @@ -191,6 +231,7 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) { column_index_date_modified = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED); while (cursor.moveToNext()) { contentPath = cursor.getString(column_index_data); + Log_OC.d(TAG,"FILESYNC CHECK File "+contentPath); isFolder = new File(contentPath).isDirectory(); if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000.0) { filesystemDataProvider.storeOrUpdateFileValue(contentPath, From 8f3b5b106c4507204f1169acb7043b35b2e639f3 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Wed, 3 Apr 2024 18:04:54 +0200 Subject: [PATCH 036/114] draft implement faster auto upload file changed scan Signed-off-by: Jonas Mayer --- .../android/utils/SyncedFolderUtilsTest.kt | 6 +- .../database/entity/SyncedFolderEntity.kt | 6 +- .../android/datamodel/SyncedFolder.java | 16 +- .../datamodel/SyncedFolderDisplayItem.java | 12 +- .../datamodel/SyncedFolderProvider.java | 11 +- .../com/owncloud/android/db/ProviderMeta.java | 3 +- .../ui/activity/SyncedFoldersActivity.kt | 15 +- .../android/utils/FilesSyncHelper.java | 156 +++++++++--------- 8 files changed, 126 insertions(+), 99 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/SyncedFolderUtilsTest.kt b/app/src/androidTest/java/com/owncloud/android/utils/SyncedFolderUtilsTest.kt index aba890bd062b..5e312853076b 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/SyncedFolderUtilsTest.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/SyncedFolderUtilsTest.kt @@ -174,7 +174,8 @@ class SyncedFolderUtilsTest : AbstractIT() { MediaFolderType.IMAGE, false, SubFolderRule.YEAR_MONTH, - false + false, + SyncedFolder.NOT_SCANNED_YET ) Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder)) } @@ -198,7 +199,8 @@ class SyncedFolderUtilsTest : AbstractIT() { MediaFolderType.IMAGE, false, SubFolderRule.YEAR_MONTH, - false + false, + SyncedFolder.NOT_SCANNED_YET ) Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder)) } diff --git a/app/src/main/java/com/nextcloud/client/database/entity/SyncedFolderEntity.kt b/app/src/main/java/com/nextcloud/client/database/entity/SyncedFolderEntity.kt index 72e57bc5de9b..8a4298cef6c0 100644 --- a/app/src/main/java/com/nextcloud/client/database/entity/SyncedFolderEntity.kt +++ b/app/src/main/java/com/nextcloud/client/database/entity/SyncedFolderEntity.kt @@ -45,6 +45,8 @@ data class SyncedFolderEntity( val hidden: Int?, @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE) val subFolderRule: Int?, - @ColumnInfo(name = ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN) - val excludeHidden: Int? + @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN) + val excludeHidden: Int?, + @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS) + val lastScanTimestampMs: Long? ) diff --git a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java index f787a550adb0..3e5b8faad590 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java +++ b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java @@ -21,6 +21,7 @@ public class SyncedFolder implements Serializable, Cloneable { public static final long UNPERSISTED_ID = Long.MIN_VALUE; public static final long EMPTY_ENABLED_TIMESTAMP_MS = -1; + public static final long NOT_SCANNED_YET = -1; private static final long serialVersionUID = -793476118299906429L; @@ -41,6 +42,7 @@ public class SyncedFolder implements Serializable, Cloneable { private boolean hidden; private SubFolderRule subfolderRule; private boolean excludeHidden; + private long lastScanTimestampMs; /** * constructor for new, to be persisted entity. @@ -75,7 +77,8 @@ public SyncedFolder(String localPath, MediaFolderType type, boolean hidden, SubFolderRule subFolderRule, - boolean excludeHidden) { + boolean excludeHidden, + long lastScanTimestampMs) { this(UNPERSISTED_ID, localPath, remotePath, @@ -91,7 +94,8 @@ public SyncedFolder(String localPath, type, hidden, subFolderRule, - excludeHidden); + excludeHidden, + lastScanTimestampMs); } /** @@ -114,7 +118,8 @@ protected SyncedFolder(long id, MediaFolderType type, boolean hidden, SubFolderRule subFolderRule, - boolean excludeHidden) { + boolean excludeHidden, + long lastScanTimestampMs) { this.id = id; this.localPath = localPath; this.remotePath = remotePath; @@ -130,6 +135,7 @@ protected SyncedFolder(long id, this.hidden = hidden; this.subfolderRule = subFolderRule; this.excludeHidden = excludeHidden; + this.lastScanTimestampMs = lastScanTimestampMs; } /** @@ -271,4 +277,8 @@ public void setExcludeHidden(boolean excludeHidden) { public boolean containsFile(String filePath){ return filePath.contains(localPath); } + + public long getLastScanTimestampMs() { return lastScanTimestampMs; } + + public void setLastScanTimestampMs(long lastScanTimestampMs) { this.lastScanTimestampMs = lastScanTimestampMs; } } diff --git a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java index 5b156f570987..2bef272cf99e 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java +++ b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java @@ -60,7 +60,8 @@ public SyncedFolderDisplayItem(long id, MediaFolderType type, boolean hidden, SubFolderRule subFolderRule, - boolean excludeHidden) { + boolean excludeHidden, + long lastScanTimestampMs) { super(id, localPath, remotePath, @@ -76,7 +77,8 @@ public SyncedFolderDisplayItem(long id, type, hidden, subFolderRule, - excludeHidden); + excludeHidden, + lastScanTimestampMs); this.filePaths = filePaths; this.folderName = folderName; this.numberOfFiles = numberOfFiles; @@ -98,7 +100,8 @@ public SyncedFolderDisplayItem(long id, MediaFolderType type, boolean hidden, SubFolderRule subFolderRule, - boolean excludeHidden) { + boolean excludeHidden, + long lastScanTimestampMs) { super(id, localPath, remotePath, @@ -114,7 +117,8 @@ public SyncedFolderDisplayItem(long id, type, hidden, subFolderRule, - excludeHidden); + excludeHidden, + lastScanTimestampMs); this.folderName = folderName; } diff --git a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index d867684829ae..51478892643a 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -360,7 +360,9 @@ private SyncedFolder createSyncedFolderFromCursor(Cursor cursor) { SubFolderRule subFolderRule = SubFolderRule.values()[cursor.getInt( cursor.getColumnIndexOrThrow(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE))]; boolean excludeHidden = cursor.getInt(cursor.getColumnIndexOrThrow( - ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN)) == 1; + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN)) == 1; + long lastScanTimestampMs = cursor.getLong(cursor.getColumnIndexOrThrow( + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS)); syncedFolder = new SyncedFolder(id, @@ -378,7 +380,8 @@ private SyncedFolder createSyncedFolderFromCursor(Cursor cursor) { type, hidden, subFolderRule, - excludeHidden); + excludeHidden, + lastScanTimestampMs); } return syncedFolder; } @@ -407,8 +410,8 @@ private ContentValues createContentValuesFromSyncedFolder(SyncedFolder syncedFol cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().id); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE, syncedFolder.getSubfolderRule().ordinal()); - cv.put(ProviderMeta.ProviderTableMeta.SYNCED_EXCLUDE_HIDDEN, syncedFolder.isExcludeHidden()); - + cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_EXCLUDE_HIDDEN, syncedFolder.isExcludeHidden()); + cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS, syncedFolder.getLastScanTimestampMs()); return cv; } diff --git a/app/src/main/java/com/owncloud/android/db/ProviderMeta.java b/app/src/main/java/com/owncloud/android/db/ProviderMeta.java index 5c948f39ca58..ee61c1dd2c7f 100644 --- a/app/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/app/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -293,7 +293,8 @@ static public class ProviderTableMeta implements BaseColumns { public static final String SYNCED_FOLDER_NAME_COLLISION_POLICY = "name_collision_policy"; public static final String SYNCED_FOLDER_HIDDEN = "hidden"; public static final String SYNCED_FOLDER_SUBFOLDER_RULE = "sub_folder_rule"; - public static final String SYNCED_EXCLUDE_HIDDEN = "exclude_hidden"; + public static final String SYNCED_FOLDER_EXCLUDE_HIDDEN = "exclude_hidden"; + public static final String SYNCED_FOLDER_LAST_SCAN_TIMESTAMP_MS = "last_scan_timestamp_ms"; // Columns of external links table public static final String EXTERNAL_LINKS_ICON_URL = "icon_url"; diff --git a/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt index bbdd2870f188..53fa9c3e60ec 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt @@ -387,7 +387,8 @@ class SyncedFoldersActivity : syncedFolder.type, syncedFolder.isHidden, syncedFolder.subfolderRule, - syncedFolder.isExcludeHidden + syncedFolder.isExcludeHidden, + syncedFolder.lastScanTimestampMs ) } @@ -418,7 +419,8 @@ class SyncedFoldersActivity : mediaFolder.type, syncedFolder.isHidden, syncedFolder.subfolderRule, - syncedFolder.isExcludeHidden + syncedFolder.isExcludeHidden, + syncedFolder.lastScanTimestampMs ) } @@ -448,7 +450,8 @@ class SyncedFoldersActivity : mediaFolder.type, false, SubFolderRule.YEAR_MONTH, - false + false, + SyncedFolder.NOT_SCANNED_YET ) } @@ -541,7 +544,8 @@ class SyncedFoldersActivity : MediaFolderType.CUSTOM, false, SubFolderRule.YEAR_MONTH, - false + false, + SyncedFolder.NOT_SCANNED_YET ) onSyncFolderSettingsClick(0, emptyCustomFolder) } else { @@ -658,7 +662,8 @@ class SyncedFoldersActivity : syncedFolder.type, syncedFolder.isHidden, syncedFolder.subFolderRule, - syncedFolder.isExcludeHidden + syncedFolder.isExcludeHidden, + SyncedFolder.NOT_SCANNED_YET ) saveOrUpdateSyncedFolder(newCustomFolder) adapter.addSyncFolderItem(newCustomFolder) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 387595d19fee..4b597c1d2bb9 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -55,6 +55,59 @@ private FilesSyncHelper() { // utility class -> private constructor } + private static void insertCustomFolderIntoDB(Path path, + SyncedFolder syncedFolder, + FilesystemDataProvider filesystemDataProvider, + long lastCheck, + long thisCheck) { + + final long enabledTimestampMs = syncedFolder.getEnabledTimestampMs(); + + try { + FileUtil.walkFileTree(path, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { + File file = path.toFile(); + if (syncedFolder.isExcludeHidden() && file.isHidden()) { + // exclude hidden file or folder + return FileVisitResult.CONTINUE; + } + + if (lastCheck != SyncedFolder.NOT_SCANNED_YET && attrs.lastModifiedTime().toMillis() < lastCheck) { + // skip files that were already checked + return FileVisitResult.CONTINUE; + } + + if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) { + // storeOrUpdateFileValue takes a few ms + // -> Rest of this file check takes not even 1 ms. + filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(), + attrs.lastModifiedTime().toMillis(), + file.isDirectory(), syncedFolder); + } + + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) { + return null; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + return FileVisitResult.CONTINUE; + } + }); + syncedFolder.setLastScanTimestampMs(thisCheck); + } catch (IOException e) { + Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e); + } + } + private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); @@ -63,92 +116,31 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) if (syncedFolder.isEnabled() && (syncedFolder.isExisting() || enabledTimestampMs >= 0)) { MediaFolderType mediaType = syncedFolder.getType(); + final long lastCheck = syncedFolder.getLastScanTimestampMs(); + final long thisCheck = System.currentTimeMillis(); + if (mediaType == MediaFolderType.IMAGE) { - FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI - , syncedFolder); + FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI, + syncedFolder, + lastCheck, thisCheck); FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - syncedFolder); + syncedFolder, + lastCheck, thisCheck); } else if (mediaType == MediaFolderType.VIDEO) { FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.INTERNAL_CONTENT_URI, - syncedFolder); + syncedFolder, + lastCheck, thisCheck); FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, - syncedFolder); + syncedFolder, + lastCheck, thisCheck); } else { - try { FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); Path path = Paths.get(syncedFolder.getLocalPath()); long startTime = System.nanoTime(); - // chick check for changes - long lastCheck = System.currentTimeMillis(); - ArrayList changedFiles = new ArrayList<>(); - FileUtil.walkFileTree(path, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { - File file = path.toFile(); - if (syncedFolder.isExcludeHidden() && file.isHidden()) { - // exclude hidden file or folder - return FileVisitResult.CONTINUE; - } - if (file.lastModified() >= lastCheck){ - changedFiles.add(file); - } - - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) { - return null; - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - return FileVisitResult.CONTINUE; - } - }); - Log_OC.d(TAG,"FILESYNC FINISHED QUICK CHECK FILE "+path+" "+(System.nanoTime() - startTime)); - startTime = System.nanoTime(); - FileUtil.walkFileTree(path, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { - File file = path.toFile(); - if (syncedFolder.isExcludeHidden() && file.isHidden()) { - // exclude hidden file or folder - return FileVisitResult.CONTINUE; - } - if (syncedFolder.isExisting() || attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) { - // storeOrUpdateFileValue takes a few millisec - // -> Rest of this file check takes not even 1 millisec. - filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(), - attrs.lastModifiedTime().toMillis(), - file.isDirectory(), syncedFolder); - } - - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) { - return null; - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - return FileVisitResult.CONTINUE; - } - }); - Log_OC.d(TAG,"FILESYNC FINISHED LONG CHECK FILE "+path+" "+(System.nanoTime() - startTime)); - - } catch (IOException e) { - Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e); - } + FilesSyncHelper.insertCustomFolderIntoDB(path, syncedFolder, filesystemDataProvider, lastCheck, thisCheck); + Log_OC.d(TAG,"FILESYNC FINISHED LONG CHECK FOLDER "+path+" "+(System.nanoTime() - startTime)); + } } } @@ -200,7 +192,7 @@ private static String getFileFromURI(String uri){ return filePath; } - private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) { + private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long lastCheckMs, long thisCheckMs) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); @@ -231,15 +223,23 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) { column_index_date_modified = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED); while (cursor.moveToNext()) { contentPath = cursor.getString(column_index_data); - Log_OC.d(TAG,"FILESYNC CHECK File "+contentPath); isFolder = new File(contentPath).isDirectory(); + + if (syncedFolder.getLastScanTimestampMs() != SyncedFolder.NOT_SCANNED_YET && + cursor.getLong(column_index_date_modified) < (lastCheckMs / 1000.0)) { + continue; + } + if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000.0) { + // storeOrUpdateFileValue takes a few ms + // -> Rest of this file check takes not even 1 ms. filesystemDataProvider.storeOrUpdateFileValue(contentPath, cursor.getLong(column_index_date_modified), isFolder, syncedFolder); } } cursor.close(); + syncedFolder.setLastScanTimestampMs(thisCheckMs); } } From 757306d1c4355bffa2370e459627ec7711f2d9af Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Mon, 8 Apr 2024 18:05:59 +0200 Subject: [PATCH 037/114] add new database version Signed-off-by: Jonas Mayer --- .../81.json | 1209 +++++++++++++++++ .../client/database/NextcloudDatabase.kt | 3 +- .../com/owncloud/android/db/ProviderMeta.java | 2 +- 3 files changed, 1212 insertions(+), 2 deletions(-) create mode 100644 app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json diff --git a/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json b/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json new file mode 100644 index 000000000000..10d076c10d38 --- /dev/null +++ b/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json @@ -0,0 +1,1209 @@ +{ + "formatVersion": 1, + "database": { + "version": 81, + "identityHash": "082a63031678a67879428f688f02d3b5", + "entities": [ + { + "tableName": "arbitrary_data", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `cloud_id` TEXT, `key` TEXT, `value` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "cloudId", + "columnName": "cloud_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "capabilities", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `assistant` INTEGER, `account` TEXT, `version_mayor` INTEGER, `version_minor` INTEGER, `version_micro` INTEGER, `version_string` TEXT, `version_edition` TEXT, `extended_support` INTEGER, `core_pollinterval` INTEGER, `sharing_api_enabled` INTEGER, `sharing_public_enabled` INTEGER, `sharing_public_password_enforced` INTEGER, `sharing_public_expire_date_enabled` INTEGER, `sharing_public_expire_date_days` INTEGER, `sharing_public_expire_date_enforced` INTEGER, `sharing_public_send_mail` INTEGER, `sharing_public_upload` INTEGER, `sharing_user_send_mail` INTEGER, `sharing_resharing` INTEGER, `sharing_federation_outgoing` INTEGER, `sharing_federation_incoming` INTEGER, `files_bigfilechunking` INTEGER, `files_undelete` INTEGER, `files_versioning` INTEGER, `external_links` INTEGER, `server_name` TEXT, `server_color` TEXT, `server_text_color` TEXT, `server_element_color` TEXT, `server_slogan` TEXT, `server_logo` TEXT, `background_url` TEXT, `end_to_end_encryption` INTEGER, `end_to_end_encryption_keys_exist` INTEGER, `end_to_end_encryption_api_version` TEXT, `activity` INTEGER, `background_default` INTEGER, `background_plain` INTEGER, `richdocument` INTEGER, `richdocument_mimetype_list` TEXT, `richdocument_direct_editing` INTEGER, `richdocument_direct_templates` INTEGER, `richdocument_optional_mimetype_list` TEXT, `sharing_public_ask_for_optional_password` INTEGER, `richdocument_product_name` TEXT, `direct_editing_etag` TEXT, `user_status` INTEGER, `user_status_supports_emoji` INTEGER, `etag` TEXT, `files_locking_version` TEXT, `groupfolders` INTEGER, `drop_account` INTEGER, `security_guard` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "assistant", + "columnName": "assistant", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "accountName", + "columnName": "account", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "versionMajor", + "columnName": "version_mayor", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionMinor", + "columnName": "version_minor", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionMicro", + "columnName": "version_micro", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionString", + "columnName": "version_string", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "versionEditor", + "columnName": "version_edition", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "extendedSupport", + "columnName": "extended_support", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "corePollinterval", + "columnName": "core_pollinterval", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingApiEnabled", + "columnName": "sharing_api_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicEnabled", + "columnName": "sharing_public_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicPasswordEnforced", + "columnName": "sharing_public_password_enforced", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateEnabled", + "columnName": "sharing_public_expire_date_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateDays", + "columnName": "sharing_public_expire_date_days", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateEnforced", + "columnName": "sharing_public_expire_date_enforced", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicSendMail", + "columnName": "sharing_public_send_mail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicUpload", + "columnName": "sharing_public_upload", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingUserSendMail", + "columnName": "sharing_user_send_mail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingResharing", + "columnName": "sharing_resharing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingFederationOutgoing", + "columnName": "sharing_federation_outgoing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingFederationIncoming", + "columnName": "sharing_federation_incoming", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesBigfilechunking", + "columnName": "files_bigfilechunking", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesUndelete", + "columnName": "files_undelete", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesVersioning", + "columnName": "files_versioning", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "externalLinks", + "columnName": "external_links", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverName", + "columnName": "server_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverColor", + "columnName": "server_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverTextColor", + "columnName": "server_text_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverElementColor", + "columnName": "server_element_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverSlogan", + "columnName": "server_slogan", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverLogo", + "columnName": "server_logo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverBackgroundUrl", + "columnName": "background_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "endToEndEncryption", + "columnName": "end_to_end_encryption", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "endToEndEncryptionKeysExist", + "columnName": "end_to_end_encryption_keys_exist", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "endToEndEncryptionApiVersion", + "columnName": "end_to_end_encryption_api_version", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "activity", + "columnName": "activity", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverBackgroundDefault", + "columnName": "background_default", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverBackgroundPlain", + "columnName": "background_plain", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocument", + "columnName": "richdocument", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentMimetypeList", + "columnName": "richdocument_mimetype_list", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "richdocumentDirectEditing", + "columnName": "richdocument_direct_editing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentTemplates", + "columnName": "richdocument_direct_templates", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentOptionalMimetypeList", + "columnName": "richdocument_optional_mimetype_list", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharingPublicAskForOptionalPassword", + "columnName": "sharing_public_ask_for_optional_password", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentProductName", + "columnName": "richdocument_product_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "directEditingEtag", + "columnName": "direct_editing_etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "userStatus", + "columnName": "user_status", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "userStatusSupportsEmoji", + "columnName": "user_status_supports_emoji", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etag", + "columnName": "etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "filesLockingVersion", + "columnName": "files_locking_version", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "groupfolders", + "columnName": "groupfolders", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "dropAccount", + "columnName": "drop_account", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "securityGuard", + "columnName": "security_guard", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "external_links", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `icon_url` TEXT, `language` TEXT, `type` INTEGER, `name` TEXT, `url` TEXT, `redirect` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "iconUrl", + "columnName": "icon_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "redirect", + "columnName": "redirect", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "filelist", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `filename` TEXT, `encrypted_filename` TEXT, `path` TEXT, `path_decrypted` TEXT, `parent` INTEGER, `created` INTEGER, `modified` INTEGER, `content_type` TEXT, `content_length` INTEGER, `media_path` TEXT, `file_owner` TEXT, `last_sync_date` INTEGER, `last_sync_date_for_data` INTEGER, `modified_at_last_sync_for_data` INTEGER, `etag` TEXT, `etag_on_server` TEXT, `share_by_link` INTEGER, `permissions` TEXT, `remote_id` TEXT, `local_id` INTEGER NOT NULL DEFAULT -1, `update_thumbnail` INTEGER, `is_downloading` INTEGER, `favorite` INTEGER, `hidden` INTEGER, `is_encrypted` INTEGER, `etag_in_conflict` TEXT, `shared_via_users` INTEGER, `mount_type` INTEGER, `has_preview` INTEGER, `unread_comments_count` INTEGER, `owner_id` TEXT, `owner_display_name` TEXT, `note` TEXT, `sharees` TEXT, `rich_workspace` TEXT, `metadata_size` TEXT, `metadata_live_photo` TEXT, `locked` INTEGER, `lock_type` INTEGER, `lock_owner` TEXT, `lock_owner_display_name` TEXT, `lock_owner_editor` TEXT, `lock_timestamp` INTEGER, `lock_timeout` INTEGER, `lock_token` TEXT, `tags` TEXT, `metadata_gps` TEXT, `e2e_counter` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "filename", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "encryptedName", + "columnName": "encrypted_filename", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pathDecrypted", + "columnName": "path_decrypted", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "parent", + "columnName": "parent", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "creation", + "columnName": "created", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "contentType", + "columnName": "content_type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentLength", + "columnName": "content_length", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "storagePath", + "columnName": "media_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "accountOwner", + "columnName": "file_owner", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastSyncDate", + "columnName": "last_sync_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastSyncDateForData", + "columnName": "last_sync_date_for_data", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "modifiedAtLastSyncForData", + "columnName": "modified_at_last_sync_for_data", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etag", + "columnName": "etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "etagOnServer", + "columnName": "etag_on_server", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharedViaLink", + "columnName": "share_by_link", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remoteId", + "columnName": "remote_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "localId", + "columnName": "local_id", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + }, + { + "fieldPath": "updateThumbnail", + "columnName": "update_thumbnail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isDownloading", + "columnName": "is_downloading", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isEncrypted", + "columnName": "is_encrypted", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etagInConflict", + "columnName": "etag_in_conflict", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharedWithSharee", + "columnName": "shared_via_users", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "mountType", + "columnName": "mount_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hasPreview", + "columnName": "has_preview", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "unreadCommentsCount", + "columnName": "unread_comments_count", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "ownerId", + "columnName": "owner_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ownerDisplayName", + "columnName": "owner_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharees", + "columnName": "sharees", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "richWorkspace", + "columnName": "rich_workspace", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataSize", + "columnName": "metadata_size", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataLivePhoto", + "columnName": "metadata_live_photo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "locked", + "columnName": "locked", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockType", + "columnName": "lock_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockOwner", + "columnName": "lock_owner", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockOwnerDisplayName", + "columnName": "lock_owner_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockOwnerEditor", + "columnName": "lock_owner_editor", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockTimestamp", + "columnName": "lock_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockTimeout", + "columnName": "lock_timeout", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockToken", + "columnName": "lock_token", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataGPS", + "columnName": "metadata_gps", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "e2eCounter", + "columnName": "e2e_counter", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "filesystem", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `is_folder` INTEGER, `found_at` INTEGER, `upload_triggered` INTEGER, `syncedfolder_id` TEXT, `crc32` TEXT, `modified_at` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileIsFolder", + "columnName": "is_folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileFoundRecently", + "columnName": "found_at", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileSentForUpload", + "columnName": "upload_triggered", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "syncedFolderId", + "columnName": "syncedfolder_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "crc32", + "columnName": "crc32", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileModified", + "columnName": "modified_at", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ocshares", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `file_source` INTEGER, `item_source` INTEGER, `share_type` INTEGER, `shate_with` TEXT, `path` TEXT, `permissions` INTEGER, `shared_date` INTEGER, `expiration_date` INTEGER, `token` TEXT, `shared_with_display_name` TEXT, `is_directory` INTEGER, `user_id` TEXT, `id_remote_shared` INTEGER, `owner_share` TEXT, `is_password_protected` INTEGER, `note` TEXT, `hide_download` INTEGER, `share_link` TEXT, `share_label` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileSource", + "columnName": "file_source", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "itemSource", + "columnName": "item_source", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareType", + "columnName": "share_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareWith", + "columnName": "shate_with", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharedDate", + "columnName": "shared_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "expirationDate", + "columnName": "expiration_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "token", + "columnName": "token", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "shareWithDisplayName", + "columnName": "shared_with_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isDirectory", + "columnName": "is_directory", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "userId", + "columnName": "user_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "idRemoteShared", + "columnName": "id_remote_shared", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "accountOwner", + "columnName": "owner_share", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isPasswordProtected", + "columnName": "is_password_protected", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "hideDownload", + "columnName": "hide_download", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareLink", + "columnName": "share_link", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "shareLabel", + "columnName": "share_label", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "synced_folders", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `wifi_only` INTEGER, `charging_only` INTEGER, `existing` INTEGER, `enabled` INTEGER, `enabled_timestamp_ms` INTEGER, `subfolder_by_date` INTEGER, `account` TEXT, `upload_option` INTEGER, `name_collision_policy` INTEGER, `type` INTEGER, `hidden` INTEGER, `sub_folder_rule` INTEGER, `exclude_hidden` INTEGER, `last_scan_timestamp_ms` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remotePath", + "columnName": "remote_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wifiOnly", + "columnName": "wifi_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "chargingOnly", + "columnName": "charging_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "existing", + "columnName": "existing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "enabledTimestampMs", + "columnName": "enabled_timestamp_ms", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "subfolderByDate", + "columnName": "subfolder_by_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "uploadAction", + "columnName": "upload_option", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "nameCollisionPolicy", + "columnName": "name_collision_policy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "subFolderRule", + "columnName": "sub_folder_rule", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "excludeHidden", + "columnName": "exclude_hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastScanTimestampMs", + "columnName": "last_scan_timestamp_ms", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "list_of_uploads", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `account_name` TEXT, `file_size` INTEGER, `status` INTEGER, `local_behaviour` INTEGER, `upload_time` INTEGER, `name_collision_policy` INTEGER, `is_create_remote_folder` INTEGER, `upload_end_timestamp` INTEGER, `last_result` INTEGER, `is_while_charging_only` INTEGER, `is_wifi_only` INTEGER, `created_by` INTEGER, `folder_unlock_token` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remotePath", + "columnName": "remote_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "accountName", + "columnName": "account_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileSize", + "columnName": "file_size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localBehaviour", + "columnName": "local_behaviour", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uploadTime", + "columnName": "upload_time", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "nameCollisionPolicy", + "columnName": "name_collision_policy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isCreateRemoteFolder", + "columnName": "is_create_remote_folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uploadEndTimestamp", + "columnName": "upload_end_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastResult", + "columnName": "last_result", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isWhileChargingOnly", + "columnName": "is_while_charging_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isWifiOnly", + "columnName": "is_wifi_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "createdBy", + "columnName": "created_by", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "folderUnlockToken", + "columnName": "folder_unlock_token", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "virtual", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `type` TEXT, `ocfile_id` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ocFileId", + "columnName": "ocfile_id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '082a63031678a67879428f688f02d3b5')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt b/app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt index f9386dc30f4b..db98e777db33 100644 --- a/app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt +++ b/app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt @@ -58,7 +58,8 @@ import com.owncloud.android.db.ProviderMeta AutoMigration(from = 76, to = 77), AutoMigration(from = 77, to = 78), AutoMigration(from = 78, to = 79, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class), - AutoMigration(from = 79, to = 80) + AutoMigration(from = 79, to = 80), + AutoMigration(from = 80, to = 81) ], exportSchema = true ) diff --git a/app/src/main/java/com/owncloud/android/db/ProviderMeta.java b/app/src/main/java/com/owncloud/android/db/ProviderMeta.java index ee61c1dd2c7f..a22d5d8400c1 100644 --- a/app/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/app/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -25,7 +25,7 @@ */ public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 80; + public static final int DB_VERSION = 81; private ProviderMeta() { // No instance From 883a9912646613019c5d8a8ecf1b3e7fb3fca303 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Mon, 8 Apr 2024 18:14:55 +0200 Subject: [PATCH 038/114] remove not used var Signed-off-by: Jonas Mayer --- app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt index 1ab6f8ce4651..2dfe8babd433 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt @@ -62,7 +62,6 @@ class FilesSyncWork( companion object { const val TAG = "FilesSyncJob" - const val SKIP_CUSTOM = "skipCustom" const val OVERRIDE_POWER_SAVING = "overridePowerSaving" const val CHANGED_FILES = "changedFiles" const val FOREGROUND_SERVICE_ID = 414 From 36f7b50f0ed23206780dc94aa08ee8b6f53f5f35 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Wed, 10 Apr 2024 13:11:49 +0200 Subject: [PATCH 039/114] Potentially broken database Signed-off-by: Jonas Mayer --- .../81.json | 1209 ----------------- .../client/SyncedFoldersActivityIT.java | 4 +- .../client/jobs/ContentObserverWork.kt | 2 + 3 files changed, 5 insertions(+), 1210 deletions(-) delete mode 100644 app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json diff --git a/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json b/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json deleted file mode 100644 index 10d076c10d38..000000000000 --- a/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json +++ /dev/null @@ -1,1209 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 81, - "identityHash": "082a63031678a67879428f688f02d3b5", - "entities": [ - { - "tableName": "arbitrary_data", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `cloud_id` TEXT, `key` TEXT, `value` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "cloudId", - "columnName": "cloud_id", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "key", - "columnName": "key", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "value", - "columnName": "value", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "capabilities", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `assistant` INTEGER, `account` TEXT, `version_mayor` INTEGER, `version_minor` INTEGER, `version_micro` INTEGER, `version_string` TEXT, `version_edition` TEXT, `extended_support` INTEGER, `core_pollinterval` INTEGER, `sharing_api_enabled` INTEGER, `sharing_public_enabled` INTEGER, `sharing_public_password_enforced` INTEGER, `sharing_public_expire_date_enabled` INTEGER, `sharing_public_expire_date_days` INTEGER, `sharing_public_expire_date_enforced` INTEGER, `sharing_public_send_mail` INTEGER, `sharing_public_upload` INTEGER, `sharing_user_send_mail` INTEGER, `sharing_resharing` INTEGER, `sharing_federation_outgoing` INTEGER, `sharing_federation_incoming` INTEGER, `files_bigfilechunking` INTEGER, `files_undelete` INTEGER, `files_versioning` INTEGER, `external_links` INTEGER, `server_name` TEXT, `server_color` TEXT, `server_text_color` TEXT, `server_element_color` TEXT, `server_slogan` TEXT, `server_logo` TEXT, `background_url` TEXT, `end_to_end_encryption` INTEGER, `end_to_end_encryption_keys_exist` INTEGER, `end_to_end_encryption_api_version` TEXT, `activity` INTEGER, `background_default` INTEGER, `background_plain` INTEGER, `richdocument` INTEGER, `richdocument_mimetype_list` TEXT, `richdocument_direct_editing` INTEGER, `richdocument_direct_templates` INTEGER, `richdocument_optional_mimetype_list` TEXT, `sharing_public_ask_for_optional_password` INTEGER, `richdocument_product_name` TEXT, `direct_editing_etag` TEXT, `user_status` INTEGER, `user_status_supports_emoji` INTEGER, `etag` TEXT, `files_locking_version` TEXT, `groupfolders` INTEGER, `drop_account` INTEGER, `security_guard` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "assistant", - "columnName": "assistant", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "accountName", - "columnName": "account", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "versionMajor", - "columnName": "version_mayor", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMinor", - "columnName": "version_minor", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionMicro", - "columnName": "version_micro", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "versionString", - "columnName": "version_string", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "versionEditor", - "columnName": "version_edition", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "extendedSupport", - "columnName": "extended_support", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "corePollinterval", - "columnName": "core_pollinterval", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingApiEnabled", - "columnName": "sharing_api_enabled", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicEnabled", - "columnName": "sharing_public_enabled", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicPasswordEnforced", - "columnName": "sharing_public_password_enforced", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicExpireDateEnabled", - "columnName": "sharing_public_expire_date_enabled", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicExpireDateDays", - "columnName": "sharing_public_expire_date_days", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicExpireDateEnforced", - "columnName": "sharing_public_expire_date_enforced", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicSendMail", - "columnName": "sharing_public_send_mail", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingPublicUpload", - "columnName": "sharing_public_upload", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingUserSendMail", - "columnName": "sharing_user_send_mail", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingResharing", - "columnName": "sharing_resharing", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingFederationOutgoing", - "columnName": "sharing_federation_outgoing", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharingFederationIncoming", - "columnName": "sharing_federation_incoming", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "filesBigfilechunking", - "columnName": "files_bigfilechunking", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "filesUndelete", - "columnName": "files_undelete", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "filesVersioning", - "columnName": "files_versioning", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "externalLinks", - "columnName": "external_links", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "serverName", - "columnName": "server_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverColor", - "columnName": "server_color", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverTextColor", - "columnName": "server_text_color", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverElementColor", - "columnName": "server_element_color", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverSlogan", - "columnName": "server_slogan", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverLogo", - "columnName": "server_logo", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "serverBackgroundUrl", - "columnName": "background_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "endToEndEncryption", - "columnName": "end_to_end_encryption", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "endToEndEncryptionKeysExist", - "columnName": "end_to_end_encryption_keys_exist", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "endToEndEncryptionApiVersion", - "columnName": "end_to_end_encryption_api_version", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "activity", - "columnName": "activity", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "serverBackgroundDefault", - "columnName": "background_default", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "serverBackgroundPlain", - "columnName": "background_plain", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "richdocument", - "columnName": "richdocument", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "richdocumentMimetypeList", - "columnName": "richdocument_mimetype_list", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "richdocumentDirectEditing", - "columnName": "richdocument_direct_editing", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "richdocumentTemplates", - "columnName": "richdocument_direct_templates", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "richdocumentOptionalMimetypeList", - "columnName": "richdocument_optional_mimetype_list", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "sharingPublicAskForOptionalPassword", - "columnName": "sharing_public_ask_for_optional_password", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "richdocumentProductName", - "columnName": "richdocument_product_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "directEditingEtag", - "columnName": "direct_editing_etag", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "userStatus", - "columnName": "user_status", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "userStatusSupportsEmoji", - "columnName": "user_status_supports_emoji", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "etag", - "columnName": "etag", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "filesLockingVersion", - "columnName": "files_locking_version", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "groupfolders", - "columnName": "groupfolders", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "dropAccount", - "columnName": "drop_account", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "securityGuard", - "columnName": "security_guard", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "external_links", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `icon_url` TEXT, `language` TEXT, `type` INTEGER, `name` TEXT, `url` TEXT, `redirect` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "iconUrl", - "columnName": "icon_url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "language", - "columnName": "language", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "url", - "columnName": "url", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "redirect", - "columnName": "redirect", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "filelist", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `filename` TEXT, `encrypted_filename` TEXT, `path` TEXT, `path_decrypted` TEXT, `parent` INTEGER, `created` INTEGER, `modified` INTEGER, `content_type` TEXT, `content_length` INTEGER, `media_path` TEXT, `file_owner` TEXT, `last_sync_date` INTEGER, `last_sync_date_for_data` INTEGER, `modified_at_last_sync_for_data` INTEGER, `etag` TEXT, `etag_on_server` TEXT, `share_by_link` INTEGER, `permissions` TEXT, `remote_id` TEXT, `local_id` INTEGER NOT NULL DEFAULT -1, `update_thumbnail` INTEGER, `is_downloading` INTEGER, `favorite` INTEGER, `hidden` INTEGER, `is_encrypted` INTEGER, `etag_in_conflict` TEXT, `shared_via_users` INTEGER, `mount_type` INTEGER, `has_preview` INTEGER, `unread_comments_count` INTEGER, `owner_id` TEXT, `owner_display_name` TEXT, `note` TEXT, `sharees` TEXT, `rich_workspace` TEXT, `metadata_size` TEXT, `metadata_live_photo` TEXT, `locked` INTEGER, `lock_type` INTEGER, `lock_owner` TEXT, `lock_owner_display_name` TEXT, `lock_owner_editor` TEXT, `lock_timestamp` INTEGER, `lock_timeout` INTEGER, `lock_token` TEXT, `tags` TEXT, `metadata_gps` TEXT, `e2e_counter` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "name", - "columnName": "filename", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "encryptedName", - "columnName": "encrypted_filename", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "path", - "columnName": "path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "pathDecrypted", - "columnName": "path_decrypted", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "parent", - "columnName": "parent", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "creation", - "columnName": "created", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "modified", - "columnName": "modified", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "contentType", - "columnName": "content_type", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "contentLength", - "columnName": "content_length", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "storagePath", - "columnName": "media_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "accountOwner", - "columnName": "file_owner", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "lastSyncDate", - "columnName": "last_sync_date", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lastSyncDateForData", - "columnName": "last_sync_date_for_data", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "modifiedAtLastSyncForData", - "columnName": "modified_at_last_sync_for_data", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "etag", - "columnName": "etag", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "etagOnServer", - "columnName": "etag_on_server", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "sharedViaLink", - "columnName": "share_by_link", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "permissions", - "columnName": "permissions", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "remoteId", - "columnName": "remote_id", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "localId", - "columnName": "local_id", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "-1" - }, - { - "fieldPath": "updateThumbnail", - "columnName": "update_thumbnail", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "isDownloading", - "columnName": "is_downloading", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "favorite", - "columnName": "favorite", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hidden", - "columnName": "hidden", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "isEncrypted", - "columnName": "is_encrypted", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "etagInConflict", - "columnName": "etag_in_conflict", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "sharedWithSharee", - "columnName": "shared_via_users", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "mountType", - "columnName": "mount_type", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hasPreview", - "columnName": "has_preview", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "unreadCommentsCount", - "columnName": "unread_comments_count", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "ownerId", - "columnName": "owner_id", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "ownerDisplayName", - "columnName": "owner_display_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "note", - "columnName": "note", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "sharees", - "columnName": "sharees", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "richWorkspace", - "columnName": "rich_workspace", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "metadataSize", - "columnName": "metadata_size", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "metadataLivePhoto", - "columnName": "metadata_live_photo", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "locked", - "columnName": "locked", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lockType", - "columnName": "lock_type", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lockOwner", - "columnName": "lock_owner", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "lockOwnerDisplayName", - "columnName": "lock_owner_display_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "lockOwnerEditor", - "columnName": "lock_owner_editor", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "lockTimestamp", - "columnName": "lock_timestamp", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lockTimeout", - "columnName": "lock_timeout", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lockToken", - "columnName": "lock_token", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "tags", - "columnName": "tags", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "metadataGPS", - "columnName": "metadata_gps", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "e2eCounter", - "columnName": "e2e_counter", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "filesystem", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `is_folder` INTEGER, `found_at` INTEGER, `upload_triggered` INTEGER, `syncedfolder_id` TEXT, `crc32` TEXT, `modified_at` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "localPath", - "columnName": "local_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "fileIsFolder", - "columnName": "is_folder", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "fileFoundRecently", - "columnName": "found_at", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "fileSentForUpload", - "columnName": "upload_triggered", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "syncedFolderId", - "columnName": "syncedfolder_id", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "crc32", - "columnName": "crc32", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "fileModified", - "columnName": "modified_at", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "ocshares", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `file_source` INTEGER, `item_source` INTEGER, `share_type` INTEGER, `shate_with` TEXT, `path` TEXT, `permissions` INTEGER, `shared_date` INTEGER, `expiration_date` INTEGER, `token` TEXT, `shared_with_display_name` TEXT, `is_directory` INTEGER, `user_id` TEXT, `id_remote_shared` INTEGER, `owner_share` TEXT, `is_password_protected` INTEGER, `note` TEXT, `hide_download` INTEGER, `share_link` TEXT, `share_label` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "fileSource", - "columnName": "file_source", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "itemSource", - "columnName": "item_source", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "shareType", - "columnName": "share_type", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "shareWith", - "columnName": "shate_with", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "path", - "columnName": "path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "permissions", - "columnName": "permissions", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "sharedDate", - "columnName": "shared_date", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "expirationDate", - "columnName": "expiration_date", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "token", - "columnName": "token", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "shareWithDisplayName", - "columnName": "shared_with_display_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "isDirectory", - "columnName": "is_directory", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "userId", - "columnName": "user_id", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "idRemoteShared", - "columnName": "id_remote_shared", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "accountOwner", - "columnName": "owner_share", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "isPasswordProtected", - "columnName": "is_password_protected", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "note", - "columnName": "note", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "hideDownload", - "columnName": "hide_download", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "shareLink", - "columnName": "share_link", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "shareLabel", - "columnName": "share_label", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "synced_folders", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `wifi_only` INTEGER, `charging_only` INTEGER, `existing` INTEGER, `enabled` INTEGER, `enabled_timestamp_ms` INTEGER, `subfolder_by_date` INTEGER, `account` TEXT, `upload_option` INTEGER, `name_collision_policy` INTEGER, `type` INTEGER, `hidden` INTEGER, `sub_folder_rule` INTEGER, `exclude_hidden` INTEGER, `last_scan_timestamp_ms` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "localPath", - "columnName": "local_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "remotePath", - "columnName": "remote_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "wifiOnly", - "columnName": "wifi_only", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "chargingOnly", - "columnName": "charging_only", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "existing", - "columnName": "existing", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "enabled", - "columnName": "enabled", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "enabledTimestampMs", - "columnName": "enabled_timestamp_ms", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "subfolderByDate", - "columnName": "subfolder_by_date", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "account", - "columnName": "account", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "uploadAction", - "columnName": "upload_option", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "nameCollisionPolicy", - "columnName": "name_collision_policy", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "hidden", - "columnName": "hidden", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "subFolderRule", - "columnName": "sub_folder_rule", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "excludeHidden", - "columnName": "exclude_hidden", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lastScanTimestampMs", - "columnName": "last_scan_timestamp_ms", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "list_of_uploads", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `account_name` TEXT, `file_size` INTEGER, `status` INTEGER, `local_behaviour` INTEGER, `upload_time` INTEGER, `name_collision_policy` INTEGER, `is_create_remote_folder` INTEGER, `upload_end_timestamp` INTEGER, `last_result` INTEGER, `is_while_charging_only` INTEGER, `is_wifi_only` INTEGER, `created_by` INTEGER, `folder_unlock_token` TEXT)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "localPath", - "columnName": "local_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "remotePath", - "columnName": "remote_path", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "accountName", - "columnName": "account_name", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "fileSize", - "columnName": "file_size", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "status", - "columnName": "status", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "localBehaviour", - "columnName": "local_behaviour", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "uploadTime", - "columnName": "upload_time", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "nameCollisionPolicy", - "columnName": "name_collision_policy", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "isCreateRemoteFolder", - "columnName": "is_create_remote_folder", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "uploadEndTimestamp", - "columnName": "upload_end_timestamp", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "lastResult", - "columnName": "last_result", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "isWhileChargingOnly", - "columnName": "is_while_charging_only", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "isWifiOnly", - "columnName": "is_wifi_only", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "createdBy", - "columnName": "created_by", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "folderUnlockToken", - "columnName": "folder_unlock_token", - "affinity": "TEXT", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - }, - { - "tableName": "virtual", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `type` TEXT, `ocfile_id` INTEGER)", - "fields": [ - { - "fieldPath": "id", - "columnName": "_id", - "affinity": "INTEGER", - "notNull": false - }, - { - "fieldPath": "type", - "columnName": "type", - "affinity": "TEXT", - "notNull": false - }, - { - "fieldPath": "ocFileId", - "columnName": "ocfile_id", - "affinity": "INTEGER", - "notNull": false - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "_id" - ] - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '082a63031678a67879428f688f02d3b5')" - ] - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java b/app/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java index 57e97d8ccda5..ba43a43af81a 100644 --- a/app/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java +++ b/app/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java @@ -14,6 +14,7 @@ import com.owncloud.android.AbstractIT; import com.owncloud.android.databinding.SyncedFoldersLayoutBinding; import com.owncloud.android.datamodel.MediaFolderType; +import com.owncloud.android.datamodel.SyncedFolder; import com.owncloud.android.datamodel.SyncedFolderDisplayItem; import com.owncloud.android.ui.activity.SyncedFoldersActivity; import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment; @@ -63,7 +64,8 @@ public void testSyncedFolderDialog() { MediaFolderType.IMAGE, false, SubFolderRule.YEAR_MONTH, - false); + false, + SyncedFolder.NOT_SCANNED_YET); SyncedFolderPreferencesDialogFragment sut = SyncedFolderPreferencesDialogFragment.newInstance(item, 0); Intent intent = new Intent(targetContext, SyncedFoldersActivity.class); diff --git a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt index caac611f7bc0..abc768e60012 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt @@ -11,6 +11,7 @@ import androidx.work.Worker import androidx.work.WorkerParameters import com.nextcloud.client.device.PowerManagementService import com.owncloud.android.datamodel.SyncedFolderProvider +import com.owncloud.android.lib.common.utils.Log_OC /** * This work is triggered when OS detects change in media folders. @@ -31,6 +32,7 @@ class ContentObserverWork( backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) if (params.triggeredContentUris.size > 0) { + Log_OC.d(TAG,"FILESYNC Content Observer detected files change") checkAndStartFileSyncJob() backgroundJobManager.startMediaFoldersDetectionJob() } From b801796aeb43aa482d15234a06b4def7be2db4ea Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Wed, 10 Apr 2024 15:04:44 +0200 Subject: [PATCH 040/114] add 81.json again Signed-off-by: Jonas Mayer --- .../81.json | 1209 +++++++++++++++++ 1 file changed, 1209 insertions(+) create mode 100644 app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json diff --git a/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json b/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json new file mode 100644 index 000000000000..10d076c10d38 --- /dev/null +++ b/app/schemas/com.nextcloud.client.database.NextcloudDatabase/81.json @@ -0,0 +1,1209 @@ +{ + "formatVersion": 1, + "database": { + "version": 81, + "identityHash": "082a63031678a67879428f688f02d3b5", + "entities": [ + { + "tableName": "arbitrary_data", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `cloud_id` TEXT, `key` TEXT, `value` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "cloudId", + "columnName": "cloud_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "capabilities", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `assistant` INTEGER, `account` TEXT, `version_mayor` INTEGER, `version_minor` INTEGER, `version_micro` INTEGER, `version_string` TEXT, `version_edition` TEXT, `extended_support` INTEGER, `core_pollinterval` INTEGER, `sharing_api_enabled` INTEGER, `sharing_public_enabled` INTEGER, `sharing_public_password_enforced` INTEGER, `sharing_public_expire_date_enabled` INTEGER, `sharing_public_expire_date_days` INTEGER, `sharing_public_expire_date_enforced` INTEGER, `sharing_public_send_mail` INTEGER, `sharing_public_upload` INTEGER, `sharing_user_send_mail` INTEGER, `sharing_resharing` INTEGER, `sharing_federation_outgoing` INTEGER, `sharing_federation_incoming` INTEGER, `files_bigfilechunking` INTEGER, `files_undelete` INTEGER, `files_versioning` INTEGER, `external_links` INTEGER, `server_name` TEXT, `server_color` TEXT, `server_text_color` TEXT, `server_element_color` TEXT, `server_slogan` TEXT, `server_logo` TEXT, `background_url` TEXT, `end_to_end_encryption` INTEGER, `end_to_end_encryption_keys_exist` INTEGER, `end_to_end_encryption_api_version` TEXT, `activity` INTEGER, `background_default` INTEGER, `background_plain` INTEGER, `richdocument` INTEGER, `richdocument_mimetype_list` TEXT, `richdocument_direct_editing` INTEGER, `richdocument_direct_templates` INTEGER, `richdocument_optional_mimetype_list` TEXT, `sharing_public_ask_for_optional_password` INTEGER, `richdocument_product_name` TEXT, `direct_editing_etag` TEXT, `user_status` INTEGER, `user_status_supports_emoji` INTEGER, `etag` TEXT, `files_locking_version` TEXT, `groupfolders` INTEGER, `drop_account` INTEGER, `security_guard` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "assistant", + "columnName": "assistant", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "accountName", + "columnName": "account", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "versionMajor", + "columnName": "version_mayor", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionMinor", + "columnName": "version_minor", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionMicro", + "columnName": "version_micro", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "versionString", + "columnName": "version_string", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "versionEditor", + "columnName": "version_edition", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "extendedSupport", + "columnName": "extended_support", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "corePollinterval", + "columnName": "core_pollinterval", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingApiEnabled", + "columnName": "sharing_api_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicEnabled", + "columnName": "sharing_public_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicPasswordEnforced", + "columnName": "sharing_public_password_enforced", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateEnabled", + "columnName": "sharing_public_expire_date_enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateDays", + "columnName": "sharing_public_expire_date_days", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicExpireDateEnforced", + "columnName": "sharing_public_expire_date_enforced", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicSendMail", + "columnName": "sharing_public_send_mail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingPublicUpload", + "columnName": "sharing_public_upload", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingUserSendMail", + "columnName": "sharing_user_send_mail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingResharing", + "columnName": "sharing_resharing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingFederationOutgoing", + "columnName": "sharing_federation_outgoing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharingFederationIncoming", + "columnName": "sharing_federation_incoming", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesBigfilechunking", + "columnName": "files_bigfilechunking", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesUndelete", + "columnName": "files_undelete", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "filesVersioning", + "columnName": "files_versioning", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "externalLinks", + "columnName": "external_links", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverName", + "columnName": "server_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverColor", + "columnName": "server_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverTextColor", + "columnName": "server_text_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverElementColor", + "columnName": "server_element_color", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverSlogan", + "columnName": "server_slogan", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverLogo", + "columnName": "server_logo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serverBackgroundUrl", + "columnName": "background_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "endToEndEncryption", + "columnName": "end_to_end_encryption", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "endToEndEncryptionKeysExist", + "columnName": "end_to_end_encryption_keys_exist", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "endToEndEncryptionApiVersion", + "columnName": "end_to_end_encryption_api_version", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "activity", + "columnName": "activity", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverBackgroundDefault", + "columnName": "background_default", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "serverBackgroundPlain", + "columnName": "background_plain", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocument", + "columnName": "richdocument", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentMimetypeList", + "columnName": "richdocument_mimetype_list", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "richdocumentDirectEditing", + "columnName": "richdocument_direct_editing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentTemplates", + "columnName": "richdocument_direct_templates", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentOptionalMimetypeList", + "columnName": "richdocument_optional_mimetype_list", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharingPublicAskForOptionalPassword", + "columnName": "sharing_public_ask_for_optional_password", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "richdocumentProductName", + "columnName": "richdocument_product_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "directEditingEtag", + "columnName": "direct_editing_etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "userStatus", + "columnName": "user_status", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "userStatusSupportsEmoji", + "columnName": "user_status_supports_emoji", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etag", + "columnName": "etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "filesLockingVersion", + "columnName": "files_locking_version", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "groupfolders", + "columnName": "groupfolders", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "dropAccount", + "columnName": "drop_account", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "securityGuard", + "columnName": "security_guard", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "external_links", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `icon_url` TEXT, `language` TEXT, `type` INTEGER, `name` TEXT, `url` TEXT, `redirect` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "iconUrl", + "columnName": "icon_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "redirect", + "columnName": "redirect", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "filelist", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `filename` TEXT, `encrypted_filename` TEXT, `path` TEXT, `path_decrypted` TEXT, `parent` INTEGER, `created` INTEGER, `modified` INTEGER, `content_type` TEXT, `content_length` INTEGER, `media_path` TEXT, `file_owner` TEXT, `last_sync_date` INTEGER, `last_sync_date_for_data` INTEGER, `modified_at_last_sync_for_data` INTEGER, `etag` TEXT, `etag_on_server` TEXT, `share_by_link` INTEGER, `permissions` TEXT, `remote_id` TEXT, `local_id` INTEGER NOT NULL DEFAULT -1, `update_thumbnail` INTEGER, `is_downloading` INTEGER, `favorite` INTEGER, `hidden` INTEGER, `is_encrypted` INTEGER, `etag_in_conflict` TEXT, `shared_via_users` INTEGER, `mount_type` INTEGER, `has_preview` INTEGER, `unread_comments_count` INTEGER, `owner_id` TEXT, `owner_display_name` TEXT, `note` TEXT, `sharees` TEXT, `rich_workspace` TEXT, `metadata_size` TEXT, `metadata_live_photo` TEXT, `locked` INTEGER, `lock_type` INTEGER, `lock_owner` TEXT, `lock_owner_display_name` TEXT, `lock_owner_editor` TEXT, `lock_timestamp` INTEGER, `lock_timeout` INTEGER, `lock_token` TEXT, `tags` TEXT, `metadata_gps` TEXT, `e2e_counter` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "filename", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "encryptedName", + "columnName": "encrypted_filename", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pathDecrypted", + "columnName": "path_decrypted", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "parent", + "columnName": "parent", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "creation", + "columnName": "created", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "contentType", + "columnName": "content_type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentLength", + "columnName": "content_length", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "storagePath", + "columnName": "media_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "accountOwner", + "columnName": "file_owner", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastSyncDate", + "columnName": "last_sync_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastSyncDateForData", + "columnName": "last_sync_date_for_data", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "modifiedAtLastSyncForData", + "columnName": "modified_at_last_sync_for_data", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etag", + "columnName": "etag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "etagOnServer", + "columnName": "etag_on_server", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharedViaLink", + "columnName": "share_by_link", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remoteId", + "columnName": "remote_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "localId", + "columnName": "local_id", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + }, + { + "fieldPath": "updateThumbnail", + "columnName": "update_thumbnail", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isDownloading", + "columnName": "is_downloading", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isEncrypted", + "columnName": "is_encrypted", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "etagInConflict", + "columnName": "etag_in_conflict", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharedWithSharee", + "columnName": "shared_via_users", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "mountType", + "columnName": "mount_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hasPreview", + "columnName": "has_preview", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "unreadCommentsCount", + "columnName": "unread_comments_count", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "ownerId", + "columnName": "owner_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ownerDisplayName", + "columnName": "owner_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sharees", + "columnName": "sharees", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "richWorkspace", + "columnName": "rich_workspace", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataSize", + "columnName": "metadata_size", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataLivePhoto", + "columnName": "metadata_live_photo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "locked", + "columnName": "locked", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockType", + "columnName": "lock_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockOwner", + "columnName": "lock_owner", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockOwnerDisplayName", + "columnName": "lock_owner_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockOwnerEditor", + "columnName": "lock_owner_editor", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lockTimestamp", + "columnName": "lock_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockTimeout", + "columnName": "lock_timeout", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lockToken", + "columnName": "lock_token", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "metadataGPS", + "columnName": "metadata_gps", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "e2eCounter", + "columnName": "e2e_counter", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "filesystem", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `is_folder` INTEGER, `found_at` INTEGER, `upload_triggered` INTEGER, `syncedfolder_id` TEXT, `crc32` TEXT, `modified_at` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileIsFolder", + "columnName": "is_folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileFoundRecently", + "columnName": "found_at", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileSentForUpload", + "columnName": "upload_triggered", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "syncedFolderId", + "columnName": "syncedfolder_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "crc32", + "columnName": "crc32", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileModified", + "columnName": "modified_at", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ocshares", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `file_source` INTEGER, `item_source` INTEGER, `share_type` INTEGER, `shate_with` TEXT, `path` TEXT, `permissions` INTEGER, `shared_date` INTEGER, `expiration_date` INTEGER, `token` TEXT, `shared_with_display_name` TEXT, `is_directory` INTEGER, `user_id` TEXT, `id_remote_shared` INTEGER, `owner_share` TEXT, `is_password_protected` INTEGER, `note` TEXT, `hide_download` INTEGER, `share_link` TEXT, `share_label` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fileSource", + "columnName": "file_source", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "itemSource", + "columnName": "item_source", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareType", + "columnName": "share_type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareWith", + "columnName": "shate_with", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "permissions", + "columnName": "permissions", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sharedDate", + "columnName": "shared_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "expirationDate", + "columnName": "expiration_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "token", + "columnName": "token", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "shareWithDisplayName", + "columnName": "shared_with_display_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isDirectory", + "columnName": "is_directory", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "userId", + "columnName": "user_id", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "idRemoteShared", + "columnName": "id_remote_shared", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "accountOwner", + "columnName": "owner_share", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isPasswordProtected", + "columnName": "is_password_protected", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "hideDownload", + "columnName": "hide_download", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "shareLink", + "columnName": "share_link", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "shareLabel", + "columnName": "share_label", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "synced_folders", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `wifi_only` INTEGER, `charging_only` INTEGER, `existing` INTEGER, `enabled` INTEGER, `enabled_timestamp_ms` INTEGER, `subfolder_by_date` INTEGER, `account` TEXT, `upload_option` INTEGER, `name_collision_policy` INTEGER, `type` INTEGER, `hidden` INTEGER, `sub_folder_rule` INTEGER, `exclude_hidden` INTEGER, `last_scan_timestamp_ms` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remotePath", + "columnName": "remote_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wifiOnly", + "columnName": "wifi_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "chargingOnly", + "columnName": "charging_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "existing", + "columnName": "existing", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "enabledTimestampMs", + "columnName": "enabled_timestamp_ms", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "subfolderByDate", + "columnName": "subfolder_by_date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "uploadAction", + "columnName": "upload_option", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "nameCollisionPolicy", + "columnName": "name_collision_policy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "subFolderRule", + "columnName": "sub_folder_rule", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "excludeHidden", + "columnName": "exclude_hidden", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastScanTimestampMs", + "columnName": "last_scan_timestamp_ms", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "list_of_uploads", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `local_path` TEXT, `remote_path` TEXT, `account_name` TEXT, `file_size` INTEGER, `status` INTEGER, `local_behaviour` INTEGER, `upload_time` INTEGER, `name_collision_policy` INTEGER, `is_create_remote_folder` INTEGER, `upload_end_timestamp` INTEGER, `last_result` INTEGER, `is_while_charging_only` INTEGER, `is_wifi_only` INTEGER, `created_by` INTEGER, `folder_unlock_token` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localPath", + "columnName": "local_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "remotePath", + "columnName": "remote_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "accountName", + "columnName": "account_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fileSize", + "columnName": "file_size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "localBehaviour", + "columnName": "local_behaviour", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uploadTime", + "columnName": "upload_time", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "nameCollisionPolicy", + "columnName": "name_collision_policy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isCreateRemoteFolder", + "columnName": "is_create_remote_folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uploadEndTimestamp", + "columnName": "upload_end_timestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastResult", + "columnName": "last_result", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isWhileChargingOnly", + "columnName": "is_while_charging_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isWifiOnly", + "columnName": "is_wifi_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "createdBy", + "columnName": "created_by", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "folderUnlockToken", + "columnName": "folder_unlock_token", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "virtual", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `type` TEXT, `ocfile_id` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ocFileId", + "columnName": "ocfile_id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '082a63031678a67879428f688f02d3b5')" + ] + } +} \ No newline at end of file From 488113a458f064c34868f7118daec8dfc91a900b Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Wed, 10 Apr 2024 17:00:26 +0200 Subject: [PATCH 041/114] Fix infinite content observer issue Signed-off-by: Jonas Mayer --- .../java/com/nextcloud/client/jobs/BackgroundJobManagerTest.kt | 2 +- .../java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/nextcloud/client/jobs/BackgroundJobManagerTest.kt b/app/src/androidTest/java/com/nextcloud/client/jobs/BackgroundJobManagerTest.kt index 21be19bbc279..e90b81ca73c0 100644 --- a/app/src/androidTest/java/com/nextcloud/client/jobs/BackgroundJobManagerTest.kt +++ b/app/src/androidTest/java/com/nextcloud/client/jobs/BackgroundJobManagerTest.kt @@ -201,7 +201,7 @@ class BackgroundJobManagerTest { fun job_is_unique_and_replaces_previous_job() { verify(workManager).enqueueUniqueWork( eq(BackgroundJobManagerImpl.JOB_CONTENT_OBSERVER), - eq(ExistingWorkPolicy.APPEND), + eq(ExistingWorkPolicy.REPLACE), argThat(IsOneTimeWorkRequest()) ) } diff --git a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt index 945e14ded7ca..0e3fd8838678 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt @@ -264,7 +264,7 @@ internal class BackgroundJobManagerImpl( .setConstraints(constrains) .build() - workManager.enqueueUniqueWork(JOB_CONTENT_OBSERVER, ExistingWorkPolicy.APPEND, request) + workManager.enqueueUniqueWork(JOB_CONTENT_OBSERVER, ExistingWorkPolicy.REPLACE, request) } override fun schedulePeriodicContactsBackup(user: User) { From 914be8e85c0b70ba7f9dbe54d0c587aaaecd1aed Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Wed, 10 Apr 2024 17:40:57 +0200 Subject: [PATCH 042/114] fix spotless Signed-off-by: Jonas Mayer --- .../com/nextcloud/client/jobs/ContentObserverWork.kt | 2 +- .../java/com/nextcloud/client/jobs/FilesSyncWork.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt index abc768e60012..a29674ef9c3e 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt @@ -32,7 +32,7 @@ class ContentObserverWork( backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) if (params.triggeredContentUris.size > 0) { - Log_OC.d(TAG,"FILESYNC Content Observer detected files change") + Log_OC.d(TAG, "FILESYNC Content Observer detected files change") checkAndStartFileSyncJob() backgroundJobManager.startMediaFoldersDetectionJob() } diff --git a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt index 2dfe8babd433..c95aabe174c2 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt @@ -94,7 +94,7 @@ class FilesSyncWork( @Suppress("MagicNumber") override fun doWork(): Result { backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) - Log_OC.d(TAG,"FILESYNC WORKER STARTED") + Log_OC.d(TAG, "FILESYNC WORKER STARTED") val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false) // If we are in power save mode, better to postpone upload @@ -114,9 +114,9 @@ class FilesSyncWork( // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem val changedFiles = inputData.getStringArray(CHANGED_FILES) - Log_OC.d(TAG,"FILESYNC WORKER CHANGED FILES: "+changedFiles.contentToString()) + Log_OC.d(TAG, "FILESYNC WORKER CHANGED FILES: " + changedFiles.contentToString()) collectChangedFiles(changedFiles) - Log_OC.d(TAG,"FILESYNC WORKER CHECKED CHANGED FILES") + Log_OC.d(TAG, "FILESYNC WORKER CHECKED CHANGED FILES") // Create all the providers we'll need val filesystemDataProvider = FilesystemDataProvider(contentResolver) @@ -143,7 +143,7 @@ class FilesSyncWork( ) } } - Log_OC.d(TAG,"FILESYNC WORKER ENDED") + Log_OC.d(TAG, "FILESYNC WORKER ENDED") val result = Result.success() backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result) return result @@ -221,7 +221,7 @@ class FilesSyncWork( needsWifi = syncedFolder.isWifiOnly uploadAction = syncedFolder.uploadAction } - Log_OC.d(TAG,"FILESYNC SCHEDULE UPLOAD OF FILE") + Log_OC.d(TAG, "FILESYNC SCHEDULE UPLOAD OF FILE") FileUploadHelper.instance().uploadNewFiles( user, localPaths, From 5c4eaac0c294429f2fc589bf67c2ef6c5f4e9850 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Thu, 11 Apr 2024 09:44:42 +0200 Subject: [PATCH 043/114] remove unnecessary log Signed-off-by: Jonas Mayer --- app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt index c95aabe174c2..f45c3542ba56 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt @@ -221,7 +221,6 @@ class FilesSyncWork( needsWifi = syncedFolder.isWifiOnly uploadAction = syncedFolder.uploadAction } - Log_OC.d(TAG, "FILESYNC SCHEDULE UPLOAD OF FILE") FileUploadHelper.instance().uploadNewFiles( user, localPaths, From 4dedc25a06093075eca89506dadaa73d96c9d230 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Tue, 16 Apr 2024 14:58:21 +0200 Subject: [PATCH 044/114] improve logs Signed-off-by: Jonas Mayer --- .../com/nextcloud/client/jobs/ContentObserverWork.kt | 2 +- .../java/com/nextcloud/client/jobs/FilesSyncWork.kt | 8 ++++---- .../com/owncloud/android/utils/FilesSyncHelper.java | 11 +++++------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt index a29674ef9c3e..718e527277bb 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt @@ -32,7 +32,7 @@ class ContentObserverWork( backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) if (params.triggeredContentUris.size > 0) { - Log_OC.d(TAG, "FILESYNC Content Observer detected files change") + Log_OC.d(TAG, "File-sync Content Observer detected files change") checkAndStartFileSyncJob() backgroundJobManager.startMediaFoldersDetectionJob() } diff --git a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt index f45c3542ba56..58b57284eee7 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt @@ -94,7 +94,7 @@ class FilesSyncWork( @Suppress("MagicNumber") override fun doWork(): Result { backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) - Log_OC.d(TAG, "FILESYNC WORKER STARTED") + Log_OC.d(TAG, "File-sync worker started") val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false) // If we are in power save mode, better to postpone upload @@ -114,9 +114,9 @@ class FilesSyncWork( // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem val changedFiles = inputData.getStringArray(CHANGED_FILES) - Log_OC.d(TAG, "FILESYNC WORKER CHANGED FILES: " + changedFiles.contentToString()) + Log_OC.d(TAG, "File-sync worker changed files from observer: " + changedFiles.contentToString()) collectChangedFiles(changedFiles) - Log_OC.d(TAG, "FILESYNC WORKER CHECKED CHANGED FILES") + Log_OC.d(TAG, "File-sync worker finished checking files.") // Create all the providers we'll need val filesystemDataProvider = FilesystemDataProvider(contentResolver) @@ -143,7 +143,7 @@ class FilesSyncWork( ) } } - Log_OC.d(TAG, "FILESYNC WORKER ENDED") + Log_OC.d(TAG, "File-sync worker finished") val result = Result.success() backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result) return result diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 4b597c1d2bb9..230dbfb775d1 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -119,6 +119,9 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) final long lastCheck = syncedFolder.getLastScanTimestampMs(); final long thisCheck = System.currentTimeMillis(); + Log_OC.d(TAG,"File-sync start check folder "+syncedFolder.getLocalPath()); + long startTime = System.nanoTime(); + if (mediaType == MediaFolderType.IMAGE) { FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI, syncedFolder, @@ -136,18 +139,15 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) } else { FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); Path path = Paths.get(syncedFolder.getLocalPath()); - - long startTime = System.nanoTime(); FilesSyncHelper.insertCustomFolderIntoDB(path, syncedFolder, filesystemDataProvider, lastCheck, thisCheck); - Log_OC.d(TAG,"FILESYNC FINISHED LONG CHECK FOLDER "+path+" "+(System.nanoTime() - startTime)); - } + + Log_OC.d(TAG,"File-sync finished full check for custom folder "+syncedFolder.getLocalPath()+" within "+(System.nanoTime() - startTime)+ "ns"); } } public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider) { for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { - Log_OC.d(TAG,"FILESYNC CHECK FOLDER "+syncedFolder.getLocalPath()); if (syncedFolder.isEnabled()) { insertAllDBEntriesForSyncedFolder(syncedFolder); } @@ -166,7 +166,6 @@ public static void insertChangedEntries(SyncedFolderProvider syncedFolderProvide filesystemDataProvider.storeOrUpdateFileValue(changedFile, file.lastModified(),file.isDirectory(), syncedFolder); - Log_OC.d(TAG,"FILESYNC ADDED UPLOAD TO DB"); break; } } From adba5bfb0e52ffb508fc9a9a14a0e451f7d650d6 Mon Sep 17 00:00:00 2001 From: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:21:52 +0200 Subject: [PATCH 045/114] Update app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> --- .../main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 230dbfb775d1..970ef1e3cb18 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -73,7 +73,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; } - if (lastCheck != SyncedFolder.NOT_SCANNED_YET && attrs.lastModifiedTime().toMillis() < lastCheck) { + if (attrs.lastModifiedTime().toMillis() < lastCheck) { // skip files that were already checked return FileVisitResult.CONTINUE; } From a7e9ca1c896dbfab4ff91c2fc9057cafd2b7af29 Mon Sep 17 00:00:00 2001 From: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:24:08 +0200 Subject: [PATCH 046/114] Update app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> --- .../main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 970ef1e3cb18..9cc3f9230c0e 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -64,7 +64,7 @@ private static void insertCustomFolderIntoDB(Path path, final long enabledTimestampMs = syncedFolder.getEnabledTimestampMs(); try { - FileUtil.walkFileTree(path, new SimpleFileVisitor() { + FileUtil.walkFileTree(path, new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { File file = path.toFile(); From 350e59d395493016e7f058fa092ecd071ade64d8 Mon Sep 17 00:00:00 2001 From: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:24:32 +0200 Subject: [PATCH 047/114] Update app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> --- .../main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 9cc3f9230c0e..ef7e5dde5e2c 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -90,7 +90,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { } @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { if (syncedFolder.isExcludeHidden() && dir.compareTo(Paths.get(syncedFolder.getLocalPath())) != 0 && dir.toFile().isHidden()) { return null; } From be7d997dc3f8a996a58525f3dee0912c0c4b5142 Mon Sep 17 00:00:00 2001 From: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:30:22 +0200 Subject: [PATCH 048/114] Update app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> --- .../main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index ef7e5dde5e2c..6d8bdad14d34 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -229,7 +229,7 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long continue; } - if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000.0) { + if (syncedFolder.isExisting() || cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000) { // storeOrUpdateFileValue takes a few ms // -> Rest of this file check takes not even 1 ms. filesystemDataProvider.storeOrUpdateFileValue(contentPath, From 7312db10688542de6088323d70eba77bdca01ecf Mon Sep 17 00:00:00 2001 From: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:30:29 +0200 Subject: [PATCH 049/114] Update app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java Co-authored-by: Tom <70907959+ZetaTom@users.noreply.github.com> Signed-off-by: Jonas Mayer <43114340+JonasMayerDev@users.noreply.github.com> --- .../main/java/com/owncloud/android/utils/FilesSyncHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 6d8bdad14d34..1f4b6783a5a8 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -225,7 +225,7 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long isFolder = new File(contentPath).isDirectory(); if (syncedFolder.getLastScanTimestampMs() != SyncedFolder.NOT_SCANNED_YET && - cursor.getLong(column_index_date_modified) < (lastCheckMs / 1000.0)) { + cursor.getLong(column_index_date_modified) < (lastCheckMs / 1000)) { continue; } From 684e842f081692d62197d04804cb5e1a7c4dfb71 Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Tue, 16 Apr 2024 15:36:02 +0200 Subject: [PATCH 050/114] rename some vars Signed-off-by: Jonas Mayer --- .../android/utils/FilesSyncHelper.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 1f4b6783a5a8..ddc8a80776e3 100644 --- a/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -39,7 +39,6 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; @@ -116,8 +115,8 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) if (syncedFolder.isEnabled() && (syncedFolder.isExisting() || enabledTimestampMs >= 0)) { MediaFolderType mediaType = syncedFolder.getType(); - final long lastCheck = syncedFolder.getLastScanTimestampMs(); - final long thisCheck = System.currentTimeMillis(); + final long lastCheckTimestampMs = syncedFolder.getLastScanTimestampMs(); + final long thisCheckTimestampMs = System.currentTimeMillis(); Log_OC.d(TAG,"File-sync start check folder "+syncedFolder.getLocalPath()); long startTime = System.nanoTime(); @@ -125,21 +124,21 @@ private static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) if (mediaType == MediaFolderType.IMAGE) { FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI, syncedFolder, - lastCheck, thisCheck); + lastCheckTimestampMs, thisCheckTimestampMs); FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, syncedFolder, - lastCheck, thisCheck); + lastCheckTimestampMs, thisCheckTimestampMs); } else if (mediaType == MediaFolderType.VIDEO) { FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.INTERNAL_CONTENT_URI, syncedFolder, - lastCheck, thisCheck); + lastCheckTimestampMs, thisCheckTimestampMs); FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, syncedFolder, - lastCheck, thisCheck); + lastCheckTimestampMs, thisCheckTimestampMs); } else { FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); Path path = Paths.get(syncedFolder.getLocalPath()); - FilesSyncHelper.insertCustomFolderIntoDB(path, syncedFolder, filesystemDataProvider, lastCheck, thisCheck); + FilesSyncHelper.insertCustomFolderIntoDB(path, syncedFolder, filesystemDataProvider, lastCheckTimestampMs, thisCheckTimestampMs); } Log_OC.d(TAG,"File-sync finished full check for custom folder "+syncedFolder.getLocalPath()+" within "+(System.nanoTime() - startTime)+ "ns"); @@ -191,7 +190,8 @@ private static String getFileFromURI(String uri){ return filePath; } - private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long lastCheckMs, long thisCheckMs) { + private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, + long lastCheckTimestampMs, long thisCheckTimestampMs) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); @@ -225,7 +225,7 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long isFolder = new File(contentPath).isDirectory(); if (syncedFolder.getLastScanTimestampMs() != SyncedFolder.NOT_SCANNED_YET && - cursor.getLong(column_index_date_modified) < (lastCheckMs / 1000)) { + cursor.getLong(column_index_date_modified) < (lastCheckTimestampMs / 1000)) { continue; } @@ -238,7 +238,7 @@ private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder, long } } cursor.close(); - syncedFolder.setLastScanTimestampMs(thisCheckMs); + syncedFolder.setLastScanTimestampMs(thisCheckTimestampMs); } } From fef1458a060179815b739fac105b7f0970ee03fc Mon Sep 17 00:00:00 2001 From: Jonas Mayer Date: Tue, 16 Apr 2024 16:24:15 +0200 Subject: [PATCH 051/114] fix unit test Signed-off-by: Jonas Mayer --- .../android/ui/activity/SyncedFoldersActivityTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java b/app/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java index 13981df525a9..49f1b5e5e848 100644 --- a/app/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java +++ b/app/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java @@ -10,6 +10,7 @@ import com.nextcloud.client.jobs.upload.FileUploadWorker; import com.nextcloud.client.preferences.SubFolderRule; import com.owncloud.android.datamodel.MediaFolderType; +import com.owncloud.android.datamodel.SyncedFolder; import com.owncloud.android.datamodel.SyncedFolderDisplayItem; import com.owncloud.android.files.services.NameCollisionPolicy; @@ -164,6 +165,7 @@ private SyncedFolderDisplayItem create(String folderName, boolean enabled) { MediaFolderType.IMAGE, false, SubFolderRule.YEAR_MONTH, - true); + true, + SyncedFolder.NOT_SCANNED_YET); } } From afeb87ff783beeeb0fe39394a4fa67d1c13e0ebc Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 15 Apr 2024 14:16:20 +0200 Subject: [PATCH 052/114] Remove assistant from navbar if banner is visible Signed-off-by: alperozturk --- .../android/ui/activity/DrawerActivity.java | 80 ++++++++++--------- .../android/utils/DrawerMenuUtil.java | 18 ++--- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index a8a0ff1c4efb..a217021eee6b 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -284,6 +284,8 @@ private void setupQuotaElement() { viewThemeUtils.material.colorProgressBar(mQuotaProgressBar); } + private boolean showTopBanner = false; + public void updateHeader() { int primaryColor = themeColorUtils.unchangedPrimaryColor(getAccount(), this); @@ -340,44 +342,52 @@ public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { // hide ecosystem apps according to user preference or in branded client LinearLayout ecosystemApps = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps); - if (getResources().getBoolean(R.bool.is_branded_client) || !preferences.isShowEcosystemApps()) { - ecosystemApps.setVisibility(View.GONE); + showTopBanner = !getResources().getBoolean(R.bool.is_branded_client) && preferences.isShowEcosystemApps(); + + if (showTopBanner) { + showBanner(ecosystemApps, primaryColor); } else { - LinearLayout notesView = ecosystemApps.findViewById(R.id.drawer_ecosystem_notes); - LinearLayout talkView = ecosystemApps.findViewById(R.id.drawer_ecosystem_talk); - LinearLayout moreView = ecosystemApps.findViewById(R.id.drawer_ecosystem_more); - LinearLayout assistantView = ecosystemApps.findViewById(R.id.drawer_ecosystem_assistant); - - notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes")); - talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2")); - moreView.setOnClickListener(v -> openAppStore("Nextcloud", true)); - assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1)); - if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) { - assistantView.setVisibility(View.VISIBLE); - } else { - assistantView.setVisibility(View.GONE); - } + MenuItem assistanMenuItem = findViewById(R.id.nav_assistant); + assistanMenuItem.setVisible(false); + ecosystemApps.setVisibility(View.GONE); + } + } - List views = Arrays.asList(notesView, talkView, moreView, assistantView); + private void showBanner(LinearLayout banner, int primaryColor) { + LinearLayout notesView = banner.findViewById(R.id.drawer_ecosystem_notes); + LinearLayout talkView = banner.findViewById(R.id.drawer_ecosystem_talk); + LinearLayout moreView = banner.findViewById(R.id.drawer_ecosystem_more); + LinearLayout assistantView = banner.findViewById(R.id.drawer_ecosystem_assistant); + + notesView.setOnClickListener(v -> openAppOrStore("it.niedermann.owncloud.notes")); + talkView.setOnClickListener(v -> openAppOrStore("com.nextcloud.talk2")); + moreView.setOnClickListener(v -> openAppStore("Nextcloud", true)); + assistantView.setOnClickListener(v -> startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title, -1)); + if (getCapabilities() != null && getCapabilities().getAssistant().isTrue()) { + assistantView.setVisibility(View.VISIBLE); + } else { + assistantView.setVisibility(View.GONE); + } - int iconColor; - if (Hct.fromInt(primaryColor).getTone() < 80.0) { - iconColor = Color.WHITE; - } else { - iconColor = getColor(R.color.grey_800_transparent); - } + List views = Arrays.asList(notesView, talkView, moreView, assistantView); - for (LinearLayout view : views) { - ImageView imageView = (ImageView) view.getChildAt(0); - imageView.setImageTintList(ColorStateList.valueOf(iconColor)); - GradientDrawable background = (GradientDrawable) imageView.getBackground(); - background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor); - TextView textView = (TextView) view.getChildAt(1); - textView.setTextColor(iconColor); - } + int iconColor; + if (Hct.fromInt(primaryColor).getTone() < 80.0) { + iconColor = Color.WHITE; + } else { + iconColor = getColor(R.color.grey_800_transparent); + } - ecosystemApps.setVisibility(View.VISIBLE); + for (LinearLayout view : views) { + ImageView imageView = (ImageView) view.getChildAt(0); + imageView.setImageTintList(ColorStateList.valueOf(iconColor)); + GradientDrawable background = (GradientDrawable) imageView.getBackground(); + background.setStroke(DisplayUtils.convertDpToPixel(1, this), iconColor); + TextView textView = (TextView) view.getChildAt(1); + textView.setTextColor(iconColor); } + + banner.setVisibility(View.VISIBLE); } /** @@ -461,11 +471,9 @@ private void filterDrawerMenu(final Menu menu, @NonNull final User user) { DrawerMenuUtil.filterTrashbinMenuItem(menu, capability); DrawerMenuUtil.filterActivityMenuItem(menu, capability); DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability); - DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources()); + DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources(), showTopBanner); DrawerMenuUtil.setupHomeMenuItem(menu, getResources()); - - DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community, - !getResources().getBoolean(R.bool.participate_enabled)); + DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community, !getResources().getBoolean(R.bool.participate_enabled)); DrawerMenuUtil.removeMenuItem(menu, R.id.nav_shared, !getResources().getBoolean(R.bool.shared_enabled)); DrawerMenuUtil.removeMenuItem(menu, R.id.nav_logout, !getResources().getBoolean(R.bool.show_drawer_logout)); } diff --git a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java index d2d942f9421e..22c59548f03f 100644 --- a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java +++ b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java @@ -27,7 +27,7 @@ public static void filterSearchMenuItems(Menu menu, User user, Resources resources) { if (user.isAnonymous()) { - filterMenuItems(menu, R.id.nav_gallery, R.id.nav_favorites); + removeMenuItem(menu, R.id.nav_gallery, R.id.nav_favorites); } if (!resources.getBoolean(R.bool.recently_modified_enabled)) { @@ -38,26 +38,26 @@ public static void filterSearchMenuItems(Menu menu, public static void filterTrashbinMenuItem(Menu menu, @Nullable OCCapability capability) { if (capability != null && capability.getFilesUndelete().isFalse() || capability != null && capability.getFilesUndelete().isUnknown()) { - filterMenuItems(menu, R.id.nav_trashbin); + removeMenuItem(menu, R.id.nav_trashbin); } } public static void filterActivityMenuItem(Menu menu, @Nullable OCCapability capability) { if (capability != null && capability.getActivity().isFalse()) { - filterMenuItems(menu, R.id.nav_activity); + removeMenuItem(menu, R.id.nav_activity); } } - public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources) { - boolean showCondition = capability != null && capability.getAssistant().isTrue() && !resources.getBoolean(R.bool.is_branded_client); - if (!showCondition) { - filterMenuItems(menu, R.id.nav_assistant); + public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources, boolean showTopBanner) { + boolean showCondition = (capability != null && capability.getAssistant().isTrue() && !resources.getBoolean(R.bool.is_branded_client)); + if (!showCondition || showTopBanner) { + removeMenuItem(menu, R.id.nav_assistant); } } public static void filterGroupfoldersMenuItem(Menu menu, @Nullable OCCapability capability) { if (capability != null && !capability.getGroupfolders().isTrue()) { - filterMenuItems(menu, R.id.nav_groupfolders); + removeMenuItem(menu, R.id.nav_groupfolders); } } @@ -74,7 +74,7 @@ public static void setupHomeMenuItem(Menu menu, Resources resources) { } } - private static void filterMenuItems(Menu menu, int... menuIds) { + private static void removeMenuItem(Menu menu, int... menuIds) { if (menuIds != null) { for (int menuId : menuIds) { menu.removeItem(menuId); From 0200e51eb75ec0a48238fb3470c63db554bb0892 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 15 Apr 2024 14:55:00 +0200 Subject: [PATCH 053/114] Toggle drawer from Assistant screen via menu button Signed-off-by: alperozturk --- .../ui/composeActivity/ComposeActivity.kt | 11 +++--- .../android/ui/activity/DrawerActivity.java | 10 ++++++ .../android/ui/activity/ToolbarActivity.java | 18 +++++++++- app/src/main/res/layout/toolbar_standard.xml | 36 +++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt index c57b39a203f5..cfedceeabffc 100644 --- a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt +++ b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt @@ -53,11 +53,14 @@ class ComposeActivity : DrawerActivity() { val titleId = intent.getIntExtra(TITLE, R.string.empty) menuItemId = intent.getIntExtra(MENU_ITEM, -1) - setupToolbar() - updateActionBarTitleAndHomeButtonByString(getString(titleId)) - if (menuItemId != -1) { setupDrawer(menuItemId!!) + } else { + setupDrawer() + } + + setupToolbarShowOnlyMenuButtonAndTitle(getString(titleId)) { + toggleDrawer() } binding.composeView.setContent { @@ -80,7 +83,7 @@ class ComposeActivity : DrawerActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { - if (isDrawerOpen) closeDrawer() else openDrawer() + toggleDrawer() true } else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index a217021eee6b..dd34c36d0017 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -506,6 +506,8 @@ private void onNavigationItemClicked(final MenuItem menuItem) { intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItem.getItemId()); startActivity(intent); } + + closeDrawer(); } else if (itemId == R.id.nav_favorites) { handleSearchEvents(new SearchEvent("", SearchRemoteOperation.SearchType.FAVORITE_SEARCH), menuItem.getItemId()); @@ -681,6 +683,14 @@ public boolean isDrawerOpen() { return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START); } + public void toggleDrawer() { + if (isDrawerOpen()) { + closeDrawer(); + } else { + openDrawer(); + } + } + /** * closes the drawer. */ diff --git a/app/src/main/java/com/owncloud/android/ui/activity/ToolbarActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/ToolbarActivity.java index 5e6dec41f0b7..b018647ed0e2 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/ToolbarActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/ToolbarActivity.java @@ -104,6 +104,22 @@ private void setupToolbar(boolean isHomeSearchToolbarShow, boolean showSortListB viewThemeUtils.material.colorMaterialTextButton(mSwitchAccountButton); } + public void setupToolbarShowOnlyMenuButtonAndTitle(String title, View.OnClickListener toggleDrawer) { + setupToolbar(false, false); + + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + } + + LinearLayout toolbar = findViewById(R.id.toolbar_linear_layout); + MaterialButton menuButton = findViewById(R.id.toolbar_menu_button); + MaterialTextView titleTextView = findViewById(R.id.toolbar_title); + titleTextView.setText(title); + toolbar.setVisibility(View.VISIBLE); + menuButton.setOnClickListener(toggleDrawer); + } + public void setupToolbar() { setupToolbar(false, false); } @@ -278,7 +294,7 @@ public void updateToolbarSubtitle(@NonNull String subtitle) { public void clearToolbarSubtitle() { ActionBar actionBar = getSupportActionBar(); - if(actionBar != null){ + if (actionBar != null) { actionBar.setSubtitle(null); } } diff --git a/app/src/main/res/layout/toolbar_standard.xml b/app/src/main/res/layout/toolbar_standard.xml index 41b3049813d2..c499ef9a97fe 100644 --- a/app/src/main/res/layout/toolbar_standard.xml +++ b/app/src/main/res/layout/toolbar_standard.xml @@ -114,6 +114,42 @@ + + + + + + + + + Date: Mon, 15 Apr 2024 15:48:31 +0200 Subject: [PATCH 054/114] Use all files as default menuItem Signed-off-by: alperozturk --- .../ui/composeActivity/ComposeActivity.kt | 14 ++++---------- .../android/ui/activity/DrawerActivity.java | 4 ++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt index cfedceeabffc..6934dabcd042 100644 --- a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt +++ b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt @@ -36,7 +36,7 @@ import java.lang.ref.WeakReference class ComposeActivity : DrawerActivity() { lateinit var binding: ActivityComposeBinding - private var menuItemId: Int? = null + private var menuItemId: Int = R.id.nav_all_files companion object { const val DESTINATION = "DESTINATION" @@ -51,13 +51,9 @@ class ComposeActivity : DrawerActivity() { val destination = intent.getSerializableArgument(DESTINATION, ComposeDestination::class.java) val titleId = intent.getIntExtra(TITLE, R.string.empty) - menuItemId = intent.getIntExtra(MENU_ITEM, -1) + menuItemId = intent.getIntExtra(MENU_ITEM, R.id.nav_all_files) - if (menuItemId != -1) { - setupDrawer(menuItemId!!) - } else { - setupDrawer() - } + setupDrawer(menuItemId) setupToolbarShowOnlyMenuButtonAndTitle(getString(titleId)) { toggleDrawer() @@ -75,9 +71,7 @@ class ComposeActivity : DrawerActivity() { override fun onResume() { super.onResume() - if (menuItemId != -1) { - setDrawerMenuItemChecked(R.id.nav_assistant) - } + setDrawerMenuItemChecked(menuItemId) } override fun onOptionsItemSelected(item: MenuItem): Boolean { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index dd34c36d0017..8929f4144e68 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -29,8 +29,10 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.SystemClock; import android.text.TextUtils; +import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -484,6 +486,8 @@ public void onMessageEvent(DummyDrawerEvent event) { } private void onNavigationItemClicked(final MenuItem menuItem) { + closeDrawer(); + setDrawerMenuItemChecked(menuItem.getItemId()); int itemId = menuItem.getItemId(); From 8e82b5e16cb6c4021297eaa5dc85476449fc0dc2 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 15 Apr 2024 16:28:15 +0200 Subject: [PATCH 055/114] Use chunks for bigger task output Signed-off-by: alperozturk --- .../client/assistant/component/TaskView.kt | 60 +++++++++---------- .../repository/AssistantMockRepository.kt | 37 ++++++++---- .../utils/extensions/StringExtensions.kt | 28 +++++++++ .../android/ui/activity/DrawerActivity.java | 1 - 4 files changed, 82 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index c09e98716c8f..92106131d2c6 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -28,6 +28,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -43,6 +44,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.extensions.statusData import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet +import com.nextcloud.utils.extensions.getRandomString +import com.nextcloud.utils.extensions.splitIntoChunks import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task @@ -53,7 +56,8 @@ fun TaskView( task: Task, showDeleteTaskAlertDialog: (Long) -> Unit ) { - var expanded by remember { mutableStateOf(false) } + var loadedChunkSize by remember { mutableIntStateOf(1) } + val taskOutputChunks = task.output?.splitIntoChunks(100) var showMoreActionsBottomSheet by remember { mutableStateOf(false) } Column( @@ -62,7 +66,11 @@ fun TaskView( .clip(RoundedCornerShape(16.dp)) .background(MaterialTheme.colorScheme.primary) .combinedClickable(onClick = { - expanded = !expanded + if (taskOutputChunks?.size != loadedChunkSize) { + loadedChunkSize += 1 + } else { + loadedChunkSize = 1 + } }, onLongClick = { showMoreActionsBottomSheet = true }) @@ -80,21 +88,23 @@ fun TaskView( Spacer(modifier = Modifier.height(16.dp)) - task.output?.let { - HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) - - Text( - text = if (expanded) it else it.take(100) + "...", - fontSize = 12.sp, - color = Color.White, - modifier = Modifier - .animateContentSize( - animationSpec = spring( - dampingRatio = Spring.DampingRatioLowBouncy, - stiffness = Spring.StiffnessLow + taskOutputChunks?.take(loadedChunkSize).let { + it?.joinToString("")?.let { output -> + HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) + + Text( + text = output, + fontSize = 12.sp, + color = Color.White, + modifier = Modifier + .animateContentSize( + animationSpec = spring( + dampingRatio = Spring.DampingRatioLowBouncy, + stiffness = Spring.StiffnessLow + ) ) - ) - ) + ) + } } Row( @@ -121,7 +131,7 @@ fun TaskView( if ((task.output?.length ?: 0) >= 100) { Image( painter = painterResource( - id = if (!expanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less + id = if (loadedChunkSize != taskOutputChunks?.size) R.drawable.ic_expand_more else R.drawable.ic_expand_less ), contentDescription = "expand content icon", colorFilter = ColorFilter.tint(Color.White) @@ -153,21 +163,7 @@ fun TaskView( @Preview @Composable private fun TaskViewPreview() { - val output = - "Lorem Ipsum is simply dummy text of the printing and " + - "typesetting industry. Lorem Ipsum has been the " + - "industry's standard dummy text ever since the 1500s, " + - "when an unknown printer took a galley of type and " + - "scrambled it to make a type specimen book. " + - "It has survived not only five centuries, but also " + - "the leap into electronic typesetting, remaining" + - " essentially unchanged. It wLorem Ipsum is simply dummy" + - " text of the printing and typesetting industry. " + - "Lorem Ipsum has been the industry's standard dummy " + - "text ever since the 1500s, when an unknown printer took a" + - " galley of type and scrambled it to make a type specimen book. " + - "It has survived not only five centuries, but also the leap " + - "into electronic typesetting, remaining essentially unchanged." + val output = "Lorem".getRandomString(100) TaskView( task = Task( diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index 754a4cb5f16d..c160e8ec8d8c 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -7,6 +7,7 @@ */ package com.nextcloud.client.assistant.repository +import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskList @@ -41,15 +42,18 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass null, "12", "", - "Give me some text", - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. " + - "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s," + - " when an unknown printer took a galley of type and scrambled it to make a type" + - " specimen book. It has survived not only five centuries, " + - "but also the leap into electronic typesetting, remaining essentially unchanged." + - " It was popularised in the 1960s with the release of Letraset sheets containing " + - "Lorem Ipsum passages, and more recently with desktop publishing software like Aldus" + - " PageMaker including versions of Lorem Ipsum", + "Give me some long text", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc consectetur condimentum augue, sit amet maximus nibh pharetra sodales. Donec blandit nulla vitae diam aliquam, vel viverra sem faucibus. Duis vitae pretium sapien. Curabitur nec libero erat. Nunc pretium eleifend mi non congue. Sed efficitur ullamcorper mi, ac faucibus mi mollis sed. Donec vestibulum enim vel massa sodales facilisis. Integer in consequat nibh. Sed id nisi erat. Donec sollicitudin pharetra massa, id sodales arcu mollis luctus. Donec sed ullamcorper nisl, non euismod metus. Proin eget sollicitudin purus.\n" + + "\n" + + "Etiam sit amet nisl pretium, facilisis ligula vel, luctus arcu. Nunc bibendum hendrerit ultricies. Integer scelerisque sem arcu, eget fermentum neque pretium in. Curabitur facilisis neque vel leo blandit tincidunt. Nullam at sodales nisl, eu porta leo. Nulla facilisi. Fusce cursus, turpis eget auctor iaculis, eros lectus posuere magna, a tristique purus nunc id quam.\n" + + "\n" + + "Nullam faucibus mauris eget magna vehicula auctor. Aliquam molestie purus quis magna mattis, sed commodo dolor condimentum. Mauris hendrerit libero ut tellus rutrum, et sagittis diam luctus. Nunc non semper neque, eget scelerisque tortor. Donec hendrerit faucibus dolor, at congue orci dignissim nec. Duis vel interdum elit, maximus elementum orci. Phasellus ut ligula id sapien dictum euismod. Vestibulum tincidunt vitae orci a congue. Nunc nec commodo urna, quis vulputate orci. Suspendisse euismod urna orci. Phasellus in metus lobortis, auctor mauris vel, venenatis nulla.\n" + + "\n" + + "Quisque lectus felis, placerat eget consequat quis, mattis et nisi. In bibendum in orci fermentum rhoncus. Nam eu nibh ex. Cras vel ligula eu quam pharetra ullamcorper. Integer a ultricies eros, at rutrum ligula. Nam laoreet convallis velit sit amet vulputate. In eleifend interdum risus, pulvinar dictum tellus. Fusce in posuere mauris, sed commodo urna. Etiam a ante id felis viverra commodo vel sed elit. Maecenas in libero turpis. Donec non elit feugiat, ullamcorper massa sit amet, lobortis turpis. Fusce mollis felis eu elementum ornare. Nulla facilisi.\n" + + "\n" + + "Curabitur sed erat vel urna luctus consequat sit amet et lacus. Donec eu tempus sapien. Morbi commodo finibus sapien, in consequat dui. Etiam ac odio magna. Cras ut nisl scelerisque, consectetur ante et, laoreet diam. Morbi efficitur, nibh ac volutpat rhoncus, urna eros cursus ipsum, non vulputate magna ipsum sit amet risus. Donec at arcu ullamcorper, pretium augue porttitor, dapibus arcu. Ut mollis velit sed tristique maximus. Duis iaculis porta ligula iaculis congue. Quisque laoreet ligula euismod faucibus consectetur. Nunc sit amet quam venenatis, dignissim nisl id, commodo augue. Nulla faucibus dui nec tortor viverra, at posuere orci sollicitudin. Sed fringilla porta lectus, id pretium tortor mattis eget. Cras suscipit mi pharetra, eleifend nisl quis, ultrices eros. Maecenas a nulla in dui blandit pellentesque non et mi.\n" + + "\n" + + "Curabitur purus mauris, scelerisque vitae metus vitae, pellentesque suscipit eros. Morbi tincidunt consequat felis at sagittis. Aenean purus elit, porta eu fringilla vitae, tincidunt ac leo. Quisque non neque et eros pretium sagittis vel sit amet sem. Fusce nec finibus elit. Proin scelerisque libero a mi blandit, quis accumsan dolor interdum. Praesent aliquet nisi in vehicula viverra. Nunc vitae accumsan neque. Donec.", "", "" ), @@ -60,10 +64,21 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass "12", "", "Give me some text 2", - "Lorem Ipsum is simply dummy text of the printing and typesetting industry.", + "Lorem".getRandomString(100), "", "" - ) + ), + Task( + 3, + "FreePrompt", + null, + "12", + "", + "Give me some text", + "Lorem".getRandomString(300), + "", + "" + ), ) ) } diff --git a/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt new file mode 100644 index 000000000000..25855676d7cd --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt @@ -0,0 +1,28 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Your Name + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.utils.extensions + +fun String.getRandomString(length: Int) : String { + val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9') + val result = (1..length) + .map { allowedChars.random() } + .joinToString("") + + return this + result +} + +fun String.splitIntoChunks(chunkSize: Int): List { + val chunks = mutableListOf() + var startIndex = 0 + while (startIndex < length) { + val endIndex = kotlin.math.min(startIndex + chunkSize, length) + chunks.add(substring(startIndex, endIndex)) + startIndex = endIndex + } + return chunks +} diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 8929f4144e68..d9a9e5ffbf40 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -32,7 +32,6 @@ import android.os.Looper; import android.os.SystemClock; import android.text.TextUtils; -import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; From ac863b3778f10b396bc86b48b7e2fbd140603437 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 15 Apr 2024 16:39:57 +0200 Subject: [PATCH 056/114] Use scrollable text view instead chunks Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 1 + .../client/assistant/component/TaskView.kt | 59 +++++++------------ .../repository/AssistantMockRepository.kt | 48 ++++++++++++++- .../utils/extensions/StringExtensions.kt | 11 ---- 4 files changed, 67 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index d7b09d4f0083..205fc677c351 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material3.ExperimentalMaterial3Api diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index 92106131d2c6..10aff5b861fb 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -22,13 +22,14 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -45,7 +46,6 @@ import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.extensions.statusData import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.nextcloud.utils.extensions.getRandomString -import com.nextcloud.utils.extensions.splitIntoChunks import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task @@ -56,8 +56,7 @@ fun TaskView( task: Task, showDeleteTaskAlertDialog: (Long) -> Unit ) { - var loadedChunkSize by remember { mutableIntStateOf(1) } - val taskOutputChunks = task.output?.splitIntoChunks(100) + val verticalScrollState = rememberScrollState(0) var showMoreActionsBottomSheet by remember { mutableStateOf(false) } Column( @@ -66,11 +65,7 @@ fun TaskView( .clip(RoundedCornerShape(16.dp)) .background(MaterialTheme.colorScheme.primary) .combinedClickable(onClick = { - if (taskOutputChunks?.size != loadedChunkSize) { - loadedChunkSize += 1 - } else { - loadedChunkSize = 1 - } + }, onLongClick = { showMoreActionsBottomSheet = true }) @@ -88,23 +83,23 @@ fun TaskView( Spacer(modifier = Modifier.height(16.dp)) - taskOutputChunks?.take(loadedChunkSize).let { - it?.joinToString("")?.let { output -> - HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) - - Text( - text = output, - fontSize = 12.sp, - color = Color.White, - modifier = Modifier - .animateContentSize( - animationSpec = spring( - dampingRatio = Spring.DampingRatioLowBouncy, - stiffness = Spring.StiffnessLow - ) + task.output?.let { + HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) + + Text( + text = it, + fontSize = 12.sp, + color = Color.White, + modifier = Modifier + .height(100.dp) + .verticalScroll(verticalScrollState) + .animateContentSize( + animationSpec = spring( + dampingRatio = Spring.DampingRatioLowBouncy, + stiffness = Spring.StiffnessLow ) - ) - } + ) + ) } Row( @@ -125,20 +120,6 @@ fun TaskView( Spacer(modifier = Modifier.width(6.dp)) Text(text = stringResource(id = descriptionId), color = Color.White) - - Spacer(modifier = Modifier.weight(1f)) - - if ((task.output?.length ?: 0) >= 100) { - Image( - painter = painterResource( - id = if (loadedChunkSize != taskOutputChunks?.size) R.drawable.ic_expand_more else R.drawable.ic_expand_less - ), - contentDescription = "expand content icon", - colorFilter = ColorFilter.tint(Color.White) - ) - } - - Spacer(modifier = Modifier.width(8.dp)) } if (showMoreActionsBottomSheet) { diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index c160e8ec8d8c..6a47406ba754 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -42,7 +42,7 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass null, "12", "", - "Give me some long text", + "Give me some long text 1", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc consectetur condimentum augue, sit amet maximus nibh pharetra sodales. Donec blandit nulla vitae diam aliquam, vel viverra sem faucibus. Duis vitae pretium sapien. Curabitur nec libero erat. Nunc pretium eleifend mi non congue. Sed efficitur ullamcorper mi, ac faucibus mi mollis sed. Donec vestibulum enim vel massa sodales facilisis. Integer in consequat nibh. Sed id nisi erat. Donec sollicitudin pharetra massa, id sodales arcu mollis luctus. Donec sed ullamcorper nisl, non euismod metus. Proin eget sollicitudin purus.\n" + "\n" + "Etiam sit amet nisl pretium, facilisis ligula vel, luctus arcu. Nunc bibendum hendrerit ultricies. Integer scelerisque sem arcu, eget fermentum neque pretium in. Curabitur facilisis neque vel leo blandit tincidunt. Nullam at sodales nisl, eu porta leo. Nulla facilisi. Fusce cursus, turpis eget auctor iaculis, eros lectus posuere magna, a tristique purus nunc id quam.\n" + @@ -74,7 +74,51 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass null, "12", "", - "Give me some text", + "Give me some text 3", + "Lorem".getRandomString(300), + "", + "" + ), + Task( + 4, + "FreePrompt", + null, + "12", + "", + "Give me some text 4", + "Lorem".getRandomString(300), + "", + "" + ), + Task( + 5, + "FreePrompt", + null, + "12", + "", + "Give me some text 5", + "Lorem".getRandomString(300), + "", + "" + ), + Task( + 6, + "FreePrompt", + null, + "12", + "", + "Give me some text 6", + "Lorem".getRandomString(300), + "", + "" + ), + Task( + 7, + "FreePrompt", + null, + "12", + "", + "Give me some text 7", "Lorem".getRandomString(300), "", "" diff --git a/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt index 25855676d7cd..8d3bba75682e 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt @@ -15,14 +15,3 @@ fun String.getRandomString(length: Int) : String { return this + result } - -fun String.splitIntoChunks(chunkSize: Int): List { - val chunks = mutableListOf() - var startIndex = 0 - while (startIndex < length) { - val endIndex = kotlin.math.min(startIndex + chunkSize, length) - chunks.add(substring(startIndex, endIndex)) - startIndex = endIndex - } - return chunks -} From 035ae37cd312905fda2cc920b2d0dd2fff655751 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 15 Apr 2024 16:40:10 +0200 Subject: [PATCH 057/114] Use scrollable text view instead chunks Signed-off-by: alperozturk --- .../main/java/com/nextcloud/client/assistant/AsssistantScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 205fc677c351..d7b09d4f0083 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material3.ExperimentalMaterial3Api From 1e3e3ae86a83601bbf0850847d8f6537ceac264b Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 10:12:12 +0200 Subject: [PATCH 058/114] Fix code analytics Signed-off-by: alperozturk --- .../client/assistant/component/TaskView.kt | 1 + .../repository/AssistantMockRepository.kt | 33 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index 10aff5b861fb..48e45a9c5b09 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -141,6 +141,7 @@ fun TaskView( } } +@Suppress("MagicNumber") @Preview @Composable private fun TaskViewPreview() { diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index 6a47406ba754..020865814d82 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -14,6 +14,7 @@ import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskType import com.owncloud.android.lib.resources.assistant.model.TaskTypes +@Suppress("MagicNumber") class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType { override fun getTaskTypes(): RemoteOperationResult { return RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { @@ -43,18 +44,26 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass "12", "", "Give me some long text 1", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc consectetur condimentum augue, sit amet maximus nibh pharetra sodales. Donec blandit nulla vitae diam aliquam, vel viverra sem faucibus. Duis vitae pretium sapien. Curabitur nec libero erat. Nunc pretium eleifend mi non congue. Sed efficitur ullamcorper mi, ac faucibus mi mollis sed. Donec vestibulum enim vel massa sodales facilisis. Integer in consequat nibh. Sed id nisi erat. Donec sollicitudin pharetra massa, id sodales arcu mollis luctus. Donec sed ullamcorper nisl, non euismod metus. Proin eget sollicitudin purus.\n" + - "\n" + - "Etiam sit amet nisl pretium, facilisis ligula vel, luctus arcu. Nunc bibendum hendrerit ultricies. Integer scelerisque sem arcu, eget fermentum neque pretium in. Curabitur facilisis neque vel leo blandit tincidunt. Nullam at sodales nisl, eu porta leo. Nulla facilisi. Fusce cursus, turpis eget auctor iaculis, eros lectus posuere magna, a tristique purus nunc id quam.\n" + - "\n" + - "Nullam faucibus mauris eget magna vehicula auctor. Aliquam molestie purus quis magna mattis, sed commodo dolor condimentum. Mauris hendrerit libero ut tellus rutrum, et sagittis diam luctus. Nunc non semper neque, eget scelerisque tortor. Donec hendrerit faucibus dolor, at congue orci dignissim nec. Duis vel interdum elit, maximus elementum orci. Phasellus ut ligula id sapien dictum euismod. Vestibulum tincidunt vitae orci a congue. Nunc nec commodo urna, quis vulputate orci. Suspendisse euismod urna orci. Phasellus in metus lobortis, auctor mauris vel, venenatis nulla.\n" + - "\n" + - "Quisque lectus felis, placerat eget consequat quis, mattis et nisi. In bibendum in orci fermentum rhoncus. Nam eu nibh ex. Cras vel ligula eu quam pharetra ullamcorper. Integer a ultricies eros, at rutrum ligula. Nam laoreet convallis velit sit amet vulputate. In eleifend interdum risus, pulvinar dictum tellus. Fusce in posuere mauris, sed commodo urna. Etiam a ante id felis viverra commodo vel sed elit. Maecenas in libero turpis. Donec non elit feugiat, ullamcorper massa sit amet, lobortis turpis. Fusce mollis felis eu elementum ornare. Nulla facilisi.\n" + - "\n" + - "Curabitur sed erat vel urna luctus consequat sit amet et lacus. Donec eu tempus sapien. Morbi commodo finibus sapien, in consequat dui. Etiam ac odio magna. Cras ut nisl scelerisque, consectetur ante et, laoreet diam. Morbi efficitur, nibh ac volutpat rhoncus, urna eros cursus ipsum, non vulputate magna ipsum sit amet risus. Donec at arcu ullamcorper, pretium augue porttitor, dapibus arcu. Ut mollis velit sed tristique maximus. Duis iaculis porta ligula iaculis congue. Quisque laoreet ligula euismod faucibus consectetur. Nunc sit amet quam venenatis, dignissim nisl id, commodo augue. Nulla faucibus dui nec tortor viverra, at posuere orci sollicitudin. Sed fringilla porta lectus, id pretium tortor mattis eget. Cras suscipit mi pharetra, eleifend nisl quis, ultrices eros. Maecenas a nulla in dui blandit pellentesque non et mi.\n" + - "\n" + - "Curabitur purus mauris, scelerisque vitae metus vitae, pellentesque suscipit eros. Morbi tincidunt consequat felis at sagittis. Aenean purus elit, porta eu fringilla vitae, tincidunt ac leo. Quisque non neque et eros pretium sagittis vel sit amet sem. Fusce nec finibus elit. Proin scelerisque libero a mi blandit, quis accumsan dolor interdum. Praesent aliquet nisi in vehicula viverra. Nunc vitae accumsan neque. Donec.", - "", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc consectetur " + + "condimentum augue, sit amet maximus nibh pharetra sodales. Donec blandit nulla vitae " + + "diam aliquam, vel viverra sem faucibus. Duis vitae pretium sapien. Curabitur nec libero " + + "erat. Nunc pretium eleifend mi non congue. Sed efficitur ullamcorper mi, ac faucibus mi" + + " mollis sed. Donec vestibulum enim vel massa sodales facilisis. Integer in consequat nibh." + + " Sed id nisi erat. Donec sollicitudin pharetra massa, id sodales arcu mollis luctus. " + + "Donec sed ullamcorper nisl, non euismod metus. Proin eget sollicitudin purus.\n" + "\n" + + "Etiam sit amet nisl pretium, facilisis ligula vel, luctus arcu. Nunc bibendum " + + "hendrerit ultricies. Integer scelerisque sem arcu, eget fermentum neque pretium in." + + " Curabitur facilisis neque vel leo blandit tincidunt. Nullam at sodales nisl, " + + "eu porta leo. Nulla facilisi. Fusce cursus, turpis eget auctor iaculis, eros " + + "lectus posuere magna, a tristique purus nunc id quam.\n" + "\n" + "Nullam faucibus " + + "mauris eget magna vehicula auctor. Aliquam molestie purus quis magna mattis, sed " + + "commodo dolor condimentum. Mauris hendrerit libero ut tellus rutrum, et sagittis diam " + + "luctus. Nunc non semper neque, eget scelerisque tortor. Donec hendrerit faucibus dolor, " + + "at congue orci dignissim nec. Duis vel interdum elit, maximus elementum orci. " + + "Phasellus ut ligula id sapien dictum euismod. Vestibulum tincidunt vitae orci a congue. " + + "unc nec commodo urna, quis vulputate orci. Suspendisse euismod urna orci. Phasellus in metus lobortis, auctor " + + "mauris vel, venenatis nulla.\n" + "\n" + "Quisque lectus felis, placerat eget consequat quis, mattis et nisi. " + + "In bibendum in orci fermentum rhoncus. Nam eu nibh ex. Cras vel ligula eu quam pharetra ullamcorper. ", "" ), Task( From 6d219c5b8c695abd754a4c96324f3e0e4b952408 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 10:29:14 +0200 Subject: [PATCH 059/114] Fix code analytics Signed-off-by: alperozturk --- .../repository/AssistantMockRepository.kt | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index 020865814d82..04efe9828ba4 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -44,26 +44,7 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass "12", "", "Give me some long text 1", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc consectetur " + - "condimentum augue, sit amet maximus nibh pharetra sodales. Donec blandit nulla vitae " + - "diam aliquam, vel viverra sem faucibus. Duis vitae pretium sapien. Curabitur nec libero " + - "erat. Nunc pretium eleifend mi non congue. Sed efficitur ullamcorper mi, ac faucibus mi" + - " mollis sed. Donec vestibulum enim vel massa sodales facilisis. Integer in consequat nibh." + - " Sed id nisi erat. Donec sollicitudin pharetra massa, id sodales arcu mollis luctus. " + - "Donec sed ullamcorper nisl, non euismod metus. Proin eget sollicitudin purus.\n" + "\n" + - "Etiam sit amet nisl pretium, facilisis ligula vel, luctus arcu. Nunc bibendum " + - "hendrerit ultricies. Integer scelerisque sem arcu, eget fermentum neque pretium in." + - " Curabitur facilisis neque vel leo blandit tincidunt. Nullam at sodales nisl, " + - "eu porta leo. Nulla facilisi. Fusce cursus, turpis eget auctor iaculis, eros " + - "lectus posuere magna, a tristique purus nunc id quam.\n" + "\n" + "Nullam faucibus " + - "mauris eget magna vehicula auctor. Aliquam molestie purus quis magna mattis, sed " + - "commodo dolor condimentum. Mauris hendrerit libero ut tellus rutrum, et sagittis diam " + - "luctus. Nunc non semper neque, eget scelerisque tortor. Donec hendrerit faucibus dolor, " + - "at congue orci dignissim nec. Duis vel interdum elit, maximus elementum orci. " + - "Phasellus ut ligula id sapien dictum euismod. Vestibulum tincidunt vitae orci a congue. " + - "unc nec commodo urna, quis vulputate orci. Suspendisse euismod urna orci. Phasellus in metus lobortis, auctor " + - "mauris vel, venenatis nulla.\n" + "\n" + "Quisque lectus felis, placerat eget consequat quis, mattis et nisi. " + - "In bibendum in orci fermentum rhoncus. Nam eu nibh ex. Cras vel ligula eu quam pharetra ullamcorper. ", + "Lorem ipsum".getRandomString(100), "" ), Task( @@ -131,7 +112,7 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass "Lorem".getRandomString(300), "", "" - ), + ) ) ) } From 05b141ef643607ddfaa4304beb9988be7f4ce5f9 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 10:29:23 +0200 Subject: [PATCH 060/114] Fix code analytics Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/component/TaskView.kt | 1 - .../java/com/nextcloud/utils/extensions/StringExtensions.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index 48e45a9c5b09..441f7033203e 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -65,7 +65,6 @@ fun TaskView( .clip(RoundedCornerShape(16.dp)) .background(MaterialTheme.colorScheme.primary) .combinedClickable(onClick = { - }, onLongClick = { showMoreActionsBottomSheet = true }) diff --git a/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt index 8d3bba75682e..9888e951de2c 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/StringExtensions.kt @@ -7,7 +7,7 @@ package com.nextcloud.utils.extensions -fun String.getRandomString(length: Int) : String { +fun String.getRandomString(length: Int): String { val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9') val result = (1..length) .map { allowedChars.random() } From 7e97a02c440b893c8ddef0d34dc77ee8346b8a8f Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 11:07:55 +0200 Subject: [PATCH 061/114] Fix code analytics Signed-off-by: alperozturk --- .../com/owncloud/android/ui/activity/DrawerActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index d9a9e5ffbf40..97253333ee35 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -533,7 +533,8 @@ private void onNavigationItemClicked(final MenuItem menuItem) { startActivity(CommunityActivity.class); } else if (itemId == R.id.nav_logout) { mCheckedMenuItem = -1; - menuItem.setChecked(false); + MenuItem isNewMenuItemChecked = menuItem.setChecked(false); + Log_OC.d(TAG,"onNavigationItemClicked nav_logout setChecked " + isNewMenuItemChecked); final Optional optionalUser = getUser(); if (optionalUser.isPresent()) { UserInfoActivity.openAccountRemovalDialog(optionalUser.get(), getSupportFragmentManager()); @@ -1143,7 +1144,8 @@ public void showFiles(boolean onDeviceOnly, boolean onlyPersonalFiles) { @Override public void avatarGenerated(Drawable avatarDrawable, Object callContext) { if (callContext instanceof MenuItem menuItem) { - menuItem.setIcon(avatarDrawable); + MenuItem newIcon = menuItem.setIcon(avatarDrawable); + Log_OC.d(TAG,"avatarGenerated new icon: " + newIcon); } else if (callContext instanceof ImageView imageView) { imageView.setImageDrawable(avatarDrawable); } else if (callContext instanceof MaterialButton materialButton) { From 3d03ea09b085cd8b23cfff7e687fc75e0d50b977 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 11:48:51 +0200 Subject: [PATCH 062/114] Fix filterAssistantMenuItem Signed-off-by: alperozturk --- .../android/ui/activity/DrawerActivity.java | 35 +++++++++++-------- .../android/utils/DrawerMenuUtil.java | 9 +++-- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 97253333ee35..3de5d66aba3a 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -29,7 +29,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.os.Looper; import android.os.SystemClock; import android.text.TextUtils; import android.view.Menu; @@ -285,14 +284,12 @@ private void setupQuotaElement() { viewThemeUtils.material.colorProgressBar(mQuotaProgressBar); } - private boolean showTopBanner = false; - public void updateHeader() { int primaryColor = themeColorUtils.unchangedPrimaryColor(getAccount(), this); + boolean isClientBranded = getResources().getBoolean(R.bool.is_branded_client); if (getAccount() != null && - getCapabilities().getServerBackground() != null && - !getResources().getBoolean(R.bool.is_branded_client)) { + getCapabilities().getServerBackground() != null && !isClientBranded) { OCCapability capability = getCapabilities(); String logo = capability.getServerLogo(); @@ -342,19 +339,29 @@ public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { } // hide ecosystem apps according to user preference or in branded client - LinearLayout ecosystemApps = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps); - showTopBanner = !getResources().getBoolean(R.bool.is_branded_client) && preferences.isShowEcosystemApps(); + LinearLayout banner = mNavigationViewHeader.findViewById(R.id.drawer_ecosystem_apps); + boolean shouldHideTopBanner = isClientBranded || !preferences.isShowEcosystemApps(); - if (showTopBanner) { - showBanner(ecosystemApps, primaryColor); + if (shouldHideTopBanner) { + hideTopBanner(banner); } else { - MenuItem assistanMenuItem = findViewById(R.id.nav_assistant); - assistanMenuItem.setVisible(false); - ecosystemApps.setVisibility(View.GONE); + showTopBanner(banner, primaryColor); + } + } + + private void hideTopBanner(LinearLayout banner) { + banner.setVisibility(View.GONE); + } + + private void hideAssistantMenuItem() { + MenuItem assistantMenuItem = findViewById(R.id.nav_assistant); + + if (assistantMenuItem != null) { + assistantMenuItem.setVisible(false); } } - private void showBanner(LinearLayout banner, int primaryColor) { + private void showTopBanner(LinearLayout banner, int primaryColor) { LinearLayout notesView = banner.findViewById(R.id.drawer_ecosystem_notes); LinearLayout talkView = banner.findViewById(R.id.drawer_ecosystem_talk); LinearLayout moreView = banner.findViewById(R.id.drawer_ecosystem_more); @@ -472,7 +479,7 @@ private void filterDrawerMenu(final Menu menu, @NonNull final User user) { DrawerMenuUtil.filterTrashbinMenuItem(menu, capability); DrawerMenuUtil.filterActivityMenuItem(menu, capability); DrawerMenuUtil.filterGroupfoldersMenuItem(menu, capability); - DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources(), showTopBanner); + DrawerMenuUtil.filterAssistantMenuItem(menu, capability, getResources()); DrawerMenuUtil.setupHomeMenuItem(menu, getResources()); DrawerMenuUtil.removeMenuItem(menu, R.id.nav_community, !getResources().getBoolean(R.bool.participate_enabled)); DrawerMenuUtil.removeMenuItem(menu, R.id.nav_shared, !getResources().getBoolean(R.bool.shared_enabled)); diff --git a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java index 22c59548f03f..0f39645319c0 100644 --- a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java +++ b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java @@ -48,9 +48,12 @@ public static void filterActivityMenuItem(Menu menu, @Nullable OCCapability capa } } - public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources, boolean showTopBanner) { - boolean showCondition = (capability != null && capability.getAssistant().isTrue() && !resources.getBoolean(R.bool.is_branded_client)); - if (!showCondition || showTopBanner) { + public static void filterAssistantMenuItem(Menu menu, @Nullable OCCapability capability, Resources resources) { + if (resources.getBoolean(R.bool.is_branded_client)) { + if (capability != null && capability.getAssistant().isFalse()) { + removeMenuItem(menu, R.id.nav_assistant); + } + } else { removeMenuItem(menu, R.id.nav_assistant); } } From d3f3d3461b58cd3fccd0873cc6fe3a463926f3ae Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 11:53:26 +0200 Subject: [PATCH 063/114] Remove unused codes Signed-off-by: alperozturk --- .../com/owncloud/android/ui/activity/DrawerActivity.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 3de5d66aba3a..35b8b8b45ade 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -353,14 +353,6 @@ private void hideTopBanner(LinearLayout banner) { banner.setVisibility(View.GONE); } - private void hideAssistantMenuItem() { - MenuItem assistantMenuItem = findViewById(R.id.nav_assistant); - - if (assistantMenuItem != null) { - assistantMenuItem.setVisible(false); - } - } - private void showTopBanner(LinearLayout banner, int primaryColor) { LinearLayout notesView = banner.findViewById(R.id.drawer_ecosystem_notes); LinearLayout talkView = banner.findViewById(R.id.drawer_ecosystem_talk); From ca51c206b38c9b3e4599b991716a200623aa5913 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 12:50:28 +0200 Subject: [PATCH 064/114] Remove unused xml Signed-off-by: alperozturk --- app/src/main/res/drawable/ic_expand_less.xml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_expand_less.xml diff --git a/app/src/main/res/drawable/ic_expand_less.xml b/app/src/main/res/drawable/ic_expand_less.xml deleted file mode 100644 index a625653901e1..000000000000 --- a/app/src/main/res/drawable/ic_expand_less.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - From a3785336d8f31529eb767e27b600f3759323d433 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 16:32:04 +0200 Subject: [PATCH 065/114] Add task detail screen Signed-off-by: alperozturk --- .../client/assistant/component/TaskView.kt | 20 ++- .../assistant/taskDetail/TaskDetailScreen.kt | 146 ++++++++++++++++++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 3 + 4 files changed, 165 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index 441f7033203e..41ccd4679339 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -22,9 +22,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -44,6 +42,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.extensions.statusData +import com.nextcloud.client.assistant.taskDetail.TaskDetailScreen import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R @@ -56,7 +55,7 @@ fun TaskView( task: Task, showDeleteTaskAlertDialog: (Long) -> Unit ) { - val verticalScrollState = rememberScrollState(0) + var showTaskDetailBottomSheet by remember { mutableStateOf(false) } var showMoreActionsBottomSheet by remember { mutableStateOf(false) } Column( @@ -65,6 +64,7 @@ fun TaskView( .clip(RoundedCornerShape(16.dp)) .background(MaterialTheme.colorScheme.primary) .combinedClickable(onClick = { + showTaskDetailBottomSheet = true }, onLongClick = { showMoreActionsBottomSheet = true }) @@ -86,12 +86,11 @@ fun TaskView( HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) Text( - text = it, + text = it.take(100), fontSize = 12.sp, color = Color.White, modifier = Modifier .height(100.dp) - .verticalScroll(verticalScrollState) .animateContentSize( animationSpec = spring( dampingRatio = Spring.DampingRatioLowBouncy, @@ -137,6 +136,16 @@ fun TaskView( dismiss = { showMoreActionsBottomSheet = false } ) } + + if (showTaskDetailBottomSheet) { + task.input?.let { input -> + task.output?.let { output -> + TaskDetailScreen(input, output) { + showTaskDetailBottomSheet = false + } + } + } + } } } @@ -159,5 +168,6 @@ private fun TaskViewPreview() { "" ) ) { + } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt new file mode 100644 index 000000000000..cb94ec7473e1 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt @@ -0,0 +1,146 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Your Name + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.taskDetail + +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.spring +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.nextcloud.utils.extensions.getRandomString +import com.owncloud.android.R + +@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) +@Composable +fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { + var showInput by remember { mutableStateOf(true) } + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + + ModalBottomSheet( + modifier = Modifier.padding(top = 32.dp), + containerColor = Color.White, + onDismissRequest = { + dismiss() + }, + sheetState = sheetState + ) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + + stickyHeader { + Row( + modifier = Modifier + .fillMaxWidth() + .background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp)) + ) { + TextInputSelectButton( + Modifier.weight(1f), + R.string.assistant_task_detail_screen_input_button_title, + showInput, + onClick = { + showInput = true + } + ) + + TextInputSelectButton( + Modifier.weight(1f), + R.string.assistant_task_detail_screen_output_button_title, + !showInput, + onClick = { + showInput = false + } + ) + } + } + + item { + Spacer(modifier = Modifier.height(16.dp)) + + Column(modifier = Modifier + .fillMaxSize() + .background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp)) + .padding(16.dp)) { + Text( + text = if (showInput) { + input + } else { + output + }, + fontSize = 12.sp, + color = Color.Black, + modifier = Modifier + .animateContentSize( + animationSpec = spring( + dampingRatio = Spring.DampingRatioLowBouncy, + stiffness = Spring.StiffnessLow + ) + ) + ) + } + + Spacer(modifier = Modifier.height(32.dp)) + } + } + } +} + +@Composable +private fun TextInputSelectButton(modifier: Modifier, titleId: Int, highlightCondition: Boolean, onClick: () -> Unit) { + Button( + onClick = onClick, + shape = RoundedCornerShape(8.dp), + colors = if (highlightCondition) { + ButtonDefaults.buttonColors(containerColor = Color.White) + } else { + ButtonDefaults.buttonColors(containerColor = colorResource(id = R.color.light_grey)) + }, + modifier = modifier + .widthIn(min = 0.dp, max = 200.dp) + .padding(horizontal = 4.dp) + ) { + Text(text = stringResource(id = titleId), color = Color.Black) + } +} + +@Suppress("MagicNumber") +@Preview +@Composable +private fun TaskDetailScreenPreview() { + TaskDetailScreen(input = "some input".getRandomString(20), output = "some output".getRandomString(3000)) { } +} diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d28fe7946729..9a721eb3e385 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -15,6 +15,7 @@ #ffffff #B3FFFFFF #333333 + #F5F5F5 #303034 #E9E8EB @color/secondary_text_color diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a2777a201eee..f99a6fd7ff51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,6 +52,9 @@ Failed In Progress + Input + Output + All Assistant From 7df114dda0195f42535a393d369d104809578ad5 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 17:09:43 +0200 Subject: [PATCH 066/114] Fix code analytics Signed-off-by: alperozturk --- .../nextcloud/client/assistant/component/TaskView.kt | 1 - .../client/assistant/taskDetail/TaskDetailScreen.kt | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index 41ccd4679339..28775341cb06 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -168,6 +168,5 @@ private fun TaskViewPreview() { "" ) ) { - } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt index cb94ec7473e1..c6a8cdc64f10 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.sp import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R +@Suppress("LongMethod") @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { @@ -62,7 +63,6 @@ fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { .fillMaxSize() .padding(16.dp) ) { - stickyHeader { Row( modifier = Modifier @@ -92,10 +92,12 @@ fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { item { Spacer(modifier = Modifier.height(16.dp)) - Column(modifier = Modifier - .fillMaxSize() - .background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp)) - .padding(16.dp)) { + Column( + modifier = Modifier + .fillMaxSize() + .background(color = colorResource(id = R.color.light_grey), shape = RoundedCornerShape(8.dp)) + .padding(16.dp) + ) { Text( text = if (showInput) { input From c5808fafe8854714dfc8ec88fa11a2df0edfb96d Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 20:08:15 +0200 Subject: [PATCH 067/114] Add completion time Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 4 +- .../assistant/extensions/TaskExtensions.kt | 5 ++ .../client/assistant/task/TaskStatus.kt | 57 +++++++++++++++++++ .../assistant/{component => task}/TaskView.kt | 44 ++------------ ...tailScreen.kt => TaskDetailBottomSheet.kt} | 24 ++++++-- .../{component => taskTypes}/TaskTypesRow.kt | 2 +- 6 files changed, 91 insertions(+), 45 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt rename app/src/main/java/com/nextcloud/client/assistant/{component => task}/TaskView.kt (72%) rename app/src/main/java/com/nextcloud/client/assistant/taskDetail/{TaskDetailScreen.kt => TaskDetailBottomSheet.kt} (90%) rename app/src/main/java/com/nextcloud/client/assistant/{component => taskTypes}/TaskTypesRow.kt (97%) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index d7b09d4f0083..4dd567c4fdf9 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -42,8 +42,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.nextcloud.client.assistant.component.AddTaskAlertDialog import com.nextcloud.client.assistant.component.CenterText -import com.nextcloud.client.assistant.component.TaskTypesRow -import com.nextcloud.client.assistant.component.TaskView +import com.nextcloud.client.assistant.taskTypes.TaskTypesRow +import com.nextcloud.client.assistant.task.TaskView import com.nextcloud.client.assistant.repository.AssistantMockRepository import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index fb7eeb0faa91..f2ff257800bd 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -35,3 +35,8 @@ fun Task.statusData(): Pair { } } } + +// TODO add +fun Task.completionDateRepresentation(): String { + return completionExpectedAt ?: "TODO IMPLEMENT IT" +} diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt new file mode 100644 index 000000000000..e011852d129c --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt @@ -0,0 +1,57 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Your Name + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.task + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.nextcloud.client.assistant.extensions.completionDateRepresentation +import com.nextcloud.client.assistant.extensions.statusData +import com.owncloud.android.lib.resources.assistant.model.Task + +@Composable +fun TaskStatus(task: Task, foregroundColor: Color) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + val (iconId, descriptionId) = task.statusData() + + Image( + painter = painterResource(id = iconId), + modifier = Modifier.size(16.dp), + colorFilter = ColorFilter.tint(foregroundColor), + contentDescription = "status icon" + ) + + Spacer(modifier = Modifier.width(6.dp)) + + Text(text = stringResource(id = descriptionId), color = foregroundColor) + + Spacer(modifier = Modifier.weight(1f)) + + Text(text = task.completionDateRepresentation(), color = foregroundColor) + + Spacer(modifier = Modifier.width(6.dp)) + } +} diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt similarity index 72% rename from app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt rename to app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 28775341cb06..865f41bf4cd1 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -1,27 +1,22 @@ /* * Nextcloud - Android Client * - * SPDX-FileCopyrightText: 2024 Alper Ozturk - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH + * SPDX-FileCopyrightText: 2024 Your Name * SPDX-License-Identifier: AGPL-3.0-or-later */ -package com.nextcloud.client.assistant.component +package com.nextcloud.client.assistant.task import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme @@ -31,18 +26,13 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.nextcloud.client.assistant.extensions.statusData -import com.nextcloud.client.assistant.taskDetail.TaskDetailScreen +import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R @@ -100,25 +90,7 @@ fun TaskView( ) } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - val (iconId, descriptionId) = task.statusData() - - Image( - painter = painterResource(id = iconId), - modifier = Modifier.size(16.dp), - colorFilter = ColorFilter.tint(Color.White), - contentDescription = "status icon" - ) - - Spacer(modifier = Modifier.width(6.dp)) - - Text(text = stringResource(id = descriptionId), color = Color.White) - } + TaskStatus(task, foregroundColor = Color.White) if (showMoreActionsBottomSheet) { val bottomSheetAction = listOf( @@ -138,12 +110,8 @@ fun TaskView( } if (showTaskDetailBottomSheet) { - task.input?.let { input -> - task.output?.let { output -> - TaskDetailScreen(input, output) { - showTaskDetailBottomSheet = false - } - } + TaskDetailBottomSheet(task) { + showTaskDetailBottomSheet = false } } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt similarity index 90% rename from app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt rename to app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index c6a8cdc64f10..70833cef0dde 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -40,13 +40,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.nextcloud.client.assistant.task.TaskStatus import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R +import com.owncloud.android.lib.resources.assistant.model.Task @Suppress("LongMethod") @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable -fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { +fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) { var showInput by remember { mutableStateOf(true) } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) @@ -100,9 +102,9 @@ fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { ) { Text( text = if (showInput) { - input + task.input ?: "" } else { - output + task.output ?: "" }, fontSize = 12.sp, color = Color.Black, @@ -116,6 +118,8 @@ fun TaskDetailScreen(input: String, output: String, dismiss: () -> Unit) { ) } + TaskStatus(task, foregroundColor = Color.Black) + Spacer(modifier = Modifier.height(32.dp)) } } @@ -144,5 +148,17 @@ private fun TextInputSelectButton(modifier: Modifier, titleId: Int, highlightCon @Preview @Composable private fun TaskDetailScreenPreview() { - TaskDetailScreen(input = "some input".getRandomString(20), output = "some output".getRandomString(3000)) { } + TaskDetailBottomSheet(task = Task( + 1, + "Free Prompt", + 0, + "1", + "1", + "Give me text".getRandomString(100), + "output".getRandomString(300), + "", + "" + )) { + + } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt similarity index 97% rename from app/src/main/java/com/nextcloud/client/assistant/component/TaskTypesRow.kt rename to app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index 6a4690b01e1c..eab26875c263 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -5,7 +5,7 @@ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH * SPDX-License-Identifier: AGPL-3.0-or-later */ -package com.nextcloud.client.assistant.component +package com.nextcloud.client.assistant.taskTypes import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Row From 1e88d0df163340b1e2dd6f3c38d6d9d43e69d54b Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 16 Apr 2024 21:52:53 +0200 Subject: [PATCH 068/114] Fix drawer close Signed-off-by: alperozturk --- .../ui/composeActivity/ComposeActivity.kt | 2 +- .../android/ui/activity/DrawerActivity.java | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt index 6934dabcd042..f0de1e08883a 100644 --- a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt +++ b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt @@ -56,7 +56,7 @@ class ComposeActivity : DrawerActivity() { setupDrawer(menuItemId) setupToolbarShowOnlyMenuButtonAndTitle(getString(titleId)) { - toggleDrawer() + openDrawer() } binding.composeView.setContent { diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 35b8b8b45ade..98d03372eb1f 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -484,8 +484,6 @@ public void onMessageEvent(DummyDrawerEvent event) { } private void onNavigationItemClicked(final MenuItem menuItem) { - closeDrawer(); - setDrawerMenuItemChecked(menuItem.getItemId()); int itemId = menuItem.getItemId(); @@ -504,6 +502,11 @@ private void onNavigationItemClicked(final MenuItem menuItem) { MainApp.showOnlyPersonalFiles(itemId == R.id.nav_personal_files); Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + if (this instanceof ComposeActivity) { + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + } + intent.setAction(FileDisplayActivity.ALL_FILES); intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItem.getItemId()); startActivity(intent); @@ -640,6 +643,11 @@ private void handleSearchEvents(SearchEvent searchEvent, int menuItemId) { private void launchActivityForSearch(SearchEvent searchEvent, int menuItemId) { Intent intent = new Intent(getApplicationContext(), FileDisplayActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + if (this instanceof ComposeActivity) { + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + } + intent.setAction(Intent.ACTION_SEARCH); intent.putExtra(OCFileListFragment.SEARCH_EVENT, searchEvent); intent.putExtra(FileDisplayActivity.DRAWER_MENU_ID, menuItemId); @@ -1136,6 +1144,11 @@ public void showFiles(boolean onDeviceOnly, boolean onlyPersonalFiles) { MainApp.showOnlyPersonalFiles(onlyPersonalFiles); Intent fileDisplayActivity = new Intent(getApplicationContext(), FileDisplayActivity.class); fileDisplayActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + if (this instanceof ComposeActivity) { + fileDisplayActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + } + fileDisplayActivity.setAction(FileDisplayActivity.ALL_FILES); startActivity(fileDisplayActivity); } From 330d0ac83708747b826a5c8b931cbaac519f4060 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 17 Apr 2024 08:09:06 +0200 Subject: [PATCH 069/114] ADD TODO Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/task/TaskStatus.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt index e011852d129c..c9179881c721 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt @@ -23,7 +23,6 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.nextcloud.client.assistant.extensions.completionDateRepresentation import com.nextcloud.client.assistant.extensions.statusData import com.owncloud.android.lib.resources.assistant.model.Task @@ -48,10 +47,12 @@ fun TaskStatus(task: Task, foregroundColor: Color) { Text(text = stringResource(id = descriptionId), color = foregroundColor) + /* Spacer(modifier = Modifier.weight(1f)) Text(text = task.completionDateRepresentation(), color = foregroundColor) Spacer(modifier = Modifier.width(6.dp)) + */ } } From 0609caadb3b68954b8f9b02e573319073230a307 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 17 Apr 2024 08:09:43 +0200 Subject: [PATCH 070/114] Fix code analytics Signed-off-by: alperozturk --- .../taskDetail/TaskDetailBottomSheet.kt | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index 70833cef0dde..e7148de43d0a 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -148,17 +148,18 @@ private fun TextInputSelectButton(modifier: Modifier, titleId: Int, highlightCon @Preview @Composable private fun TaskDetailScreenPreview() { - TaskDetailBottomSheet(task = Task( - 1, - "Free Prompt", - 0, - "1", - "1", - "Give me text".getRandomString(100), - "output".getRandomString(300), - "", - "" - )) { - + TaskDetailBottomSheet( + task = Task( + 1, + "Free Prompt", + 0, + "1", + "1", + "Give me text".getRandomString(100), + "output".getRandomString(300), + "", + "" + ) + ) { } } From 8d73fd74011657444e116dd86488539e0f91a809 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 07:16:27 +0000 Subject: [PATCH 071/114] Update ubuntu:jammy Docker digest to 1b8d8ff Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b6f52d89c6d5..8f068afcada6 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:jammy@sha256:77906da86b60585ce12215807090eb327e7386c8fafb5402369e421f44eff17e +FROM ubuntu:jammy@sha256:1b8d8ff4777f36f19bfe73ee4df61e3a0b789caeff29caa019539ec7c9a57f95 ARG DEBIAN_FRONTEND=noninteractive ENV ANDROID_HOME=/usr/lib/android-sdk From 58ec17a63f1bb8701f65bda81b4d5683a585640f Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 17 Apr 2024 10:10:33 +0200 Subject: [PATCH 072/114] suppress spotbugs Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/datamodel/FileDataStorageManager.java | 1 + .../com/owncloud/android/operations/RefreshFolderOperation.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index bcdf36f2f940..d0d9761ef020 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -2337,6 +2337,7 @@ public String getEncryptedRemotePath(String decryptedRemotePath) { return null; } + @SuppressFBWarnings("OCP") private List> getDecryptedFileNamesAndEncryptedRemotePaths(List fileList) { List> result = new ArrayList<>(); diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index b428efc8feb7..33b31c44dfeb 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -58,6 +58,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.localbroadcastmanager.content.LocalBroadcastManager; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; @@ -601,6 +602,7 @@ public static Object getDecryptedFolderMetadata(boolean encryptedAncestor, return metadata; } + @SuppressFBWarnings("CE") private static void setMimeTypeAndDecryptedRemotePath(OCFile updatedFile, FileDataStorageManager storageManager, String decryptedFileName, String mimetype) { OCFile parentFile = storageManager.getFileById(updatedFile.getParentId()); From c2530c8cfc7914471ba634e52f091376336f28e1 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 17 Apr 2024 10:42:22 +0200 Subject: [PATCH 073/114] suppress spotbugs Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/datamodel/FileDataStorageManager.java | 1 + .../com/owncloud/android/operations/RefreshFolderOperation.java | 1 + 2 files changed, 2 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index d0d9761ef020..214c9820a77d 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -1705,6 +1705,7 @@ public void deleteFileInMediaScan(String path) { } } + @SuppressFBWarnings("PSC") public void saveConflict(OCFile ocFile, String etagInConflict) { ContentValues cv = new ContentValues(); if (!ocFile.isDown()) { diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 33b31c44dfeb..7da4f995172c 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -738,6 +738,7 @@ private void setLocalFileDataOnUpdatedFile(OCFile remoteFile, OCFile localFile, } @NonNull + @SuppressFBWarnings("OCP") public static Map prefillLocalFilesMap(Object metadata, List localFiles) { Map localFilesMap = Maps.newHashMapWithExpectedSize(localFiles.size()); From 6c7a9211e51f46b7dd5579c9678128d368867067 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 17 Apr 2024 12:00:45 +0200 Subject: [PATCH 074/114] outdated version is now NC26 Signed-off-by: tobiasKaminsky --- app/src/main/java/com/owncloud/android/MainApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/MainApp.java b/app/src/main/java/com/owncloud/android/MainApp.java index ae7e03f7368d..f6d754b402ab 100644 --- a/app/src/main/java/com/owncloud/android/MainApp.java +++ b/app/src/main/java/com/owncloud/android/MainApp.java @@ -124,7 +124,7 @@ * Contains methods to build the "static" strings. These strings were before constants in different classes. */ public class MainApp extends MultiDexApplication implements HasAndroidInjector { - public static final OwnCloudVersion OUTDATED_SERVER_VERSION = NextcloudVersion.nextcloud_23; + public static final OwnCloudVersion OUTDATED_SERVER_VERSION = NextcloudVersion.nextcloud_26; public static final OwnCloudVersion MINIMUM_SUPPORTED_SERVER_VERSION = OwnCloudVersion.nextcloud_16; private static final String TAG = MainApp.class.getSimpleName(); From 260b4ac08f8059a0b015e9f383e321c0bf0f9851 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 17 Apr 2024 12:14:00 +0200 Subject: [PATCH 075/114] Bump master to 3.30 alpha Signed-off-by: tobiasKaminsky --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 261956d6661c..e912466a6672 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ configurations.configureEach { // semantic versioning for version code def versionMajor = 3 -def versionMinor = 29 +def versionMinor = 30 def versionPatch = 0 def versionBuild = 0 // 0-50=Alpha / 51-98=RC / 90-99=stable From eda6fdaa04a556a1ee7479ea0f8f6d55a9651fbf Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Wed, 17 Apr 2024 10:14:16 +0000 Subject: [PATCH 076/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ar/strings.xml | 3 +- app/src/main/res/values-b+en+001/strings.xml | 4 +- app/src/main/res/values-bg-rBG/strings.xml | 2 - app/src/main/res/values-br/strings.xml | 2 - app/src/main/res/values-ca/strings.xml | 2 - app/src/main/res/values-cs-rCZ/strings.xml | 3 +- app/src/main/res/values-da/strings.xml | 2 - app/src/main/res/values-de/strings.xml | 4 +- app/src/main/res/values-el/strings.xml | 2 - app/src/main/res/values-eo/strings.xml | 1 - app/src/main/res/values-es-rAR/strings.xml | 2 - app/src/main/res/values-es-rCL/strings.xml | 1 - app/src/main/res/values-es-rCO/strings.xml | 1 - app/src/main/res/values-es-rCR/strings.xml | 1 - app/src/main/res/values-es-rDO/strings.xml | 1 - app/src/main/res/values-es-rEC/strings.xml | 2 - app/src/main/res/values-es-rGT/strings.xml | 1 - app/src/main/res/values-es-rMX/strings.xml | 2 - app/src/main/res/values-es-rSV/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 4 +- app/src/main/res/values-et-rEE/strings.xml | 2 - app/src/main/res/values-eu/strings.xml | 4 +- app/src/main/res/values-fa/strings.xml | 2 - app/src/main/res/values-fi-rFI/strings.xml | 2 - app/src/main/res/values-fr/strings.xml | 4 +- app/src/main/res/values-gd/strings.xml | 2 - app/src/main/res/values-gl/strings.xml | 3 +- app/src/main/res/values-hr/strings.xml | 2 - app/src/main/res/values-hu-rHU/strings.xml | 2 - app/src/main/res/values-in/strings.xml | 2 - app/src/main/res/values-is/strings.xml | 2 - app/src/main/res/values-it/strings.xml | 2 - app/src/main/res/values-iw/strings.xml | 2 - app/src/main/res/values-ja-rJP/strings.xml | 2 - app/src/main/res/values-ka-rGE/strings.xml | 506 ------------------- app/src/main/res/values-ka/strings.xml | 2 - app/src/main/res/values-ko/strings.xml | 2 - app/src/main/res/values-lo/strings.xml | 2 - app/src/main/res/values-lt-rLT/strings.xml | 2 - app/src/main/res/values-lv/strings.xml | 2 - app/src/main/res/values-mk/strings.xml | 2 - app/src/main/res/values-nb-rNO/strings.xml | 4 +- app/src/main/res/values-nl/strings.xml | 2 - app/src/main/res/values-pl/strings.xml | 2 - app/src/main/res/values-pt-rBR/strings.xml | 4 +- app/src/main/res/values-pt-rPT/strings.xml | 2 - app/src/main/res/values-ro/strings.xml | 2 - app/src/main/res/values-ru/strings.xml | 2 - app/src/main/res/values-sc/strings.xml | 2 - app/src/main/res/values-sk-rSK/strings.xml | 2 - app/src/main/res/values-sl/strings.xml | 2 - app/src/main/res/values-sq/strings.xml | 2 - app/src/main/res/values-sr-rSP/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 4 +- app/src/main/res/values-sv/strings.xml | 3 +- app/src/main/res/values-th-rTH/strings.xml | 2 - app/src/main/res/values-tk/strings.xml | 2 - app/src/main/res/values-tr/strings.xml | 4 +- app/src/main/res/values-uk/strings.xml | 2 - app/src/main/res/values-vi/strings.xml | 2 - app/src/main/res/values-zh-rCN/strings.xml | 3 +- app/src/main/res/values-zh-rHK/strings.xml | 4 +- app/src/main/res/values-zh-rTW/strings.xml | 4 +- 63 files changed, 27 insertions(+), 622 deletions(-) delete mode 100644 app/src/main/res/values-ka-rGE/strings.xml diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 67b371d125ac..f4420e1201af 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -7,7 +7,6 @@ فشل إنشاء الحساب أيقونة الحساب الحساب غير موجود - مسح الملفات التي فشل رفعها تعديل إزالة جميع التنبيهات تفريغ سلة المهملات @@ -57,6 +56,7 @@ تعذّر جلب أنواع المهام. قم رجاءً بالتحقُّق من اتصالك بالإنترنت. المُساعِد غير معروف + المُخرَجَات الحساب المرتبط غير موجود! فشل الوصول لـ: %1$s هذا الحساب لم تتم إضافته في هذا الجهاز بعد @@ -171,7 +171,6 @@ هل توَدُّ حقاً حذف %1$s وما يحتويه؟ هل توَدُّ حقاً حذف العناصر المختارة وما يحتوّه؟ محلياً فقط - خطأ في إنشاء حوار التعارض! ملف متضارب %1$s ملف محلي إذا قمت باختيار كلا الاصدارين, الملف المحلي سيحتوي على رقم ملحق باسم الملف. diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index cb05124dde4e..34545c31d13e 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -7,7 +7,6 @@ Account creation failed Account icon Account not found! - Clear failed uploads Edit Clear all notifications Empty trash bin @@ -57,6 +56,8 @@ Unable to fetch task types, please check your internet connection. Assistant Unknown + Input + Output Associated account not found! Access failed: %1$s The account is not added on this device yet @@ -171,7 +172,6 @@ Do you really want to delete %1$s and its content? Do you really want to delete the selected items and their contents? Local only - Error creating conflict dialogue! Conflicting file %1$s Local file If you select both versions, the local file will have a number appended to its name. diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 33f8be278b6a..ed821129395f 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -7,7 +7,6 @@ Създаването на профила се провали Профил Няма намерен профил! - Изчисти провалените качвания Променяне Премахнете известията Изпразване на кошчето @@ -153,7 +152,6 @@ Наистина ли желаете %1$s и съдържанието ѝ да бъдат изтрито? Наистина ли желаете избраните елементи и съдържанието им да бъдат премахнати? Само локално - Грешка при създаване на диалог за конфликт! Несъвместим файл %1$s Локален файл Ако изберете и двете версии, ще бъде добавен номер към името на локалния файл. diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index f2b9de3335e5..ddafa9066641 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -7,7 +7,6 @@ C\'hwitet eo bet ar c\'houiñ eus anr c\'hont Ikonenn kont N\'o ket bet kavet ar c\'hont - Lemmel ar pellgasoù chwitet Cheñch Lemmel toud ar c\'hemenadennoù Kas/Rannan @@ -136,7 +135,6 @@ Sur oc\'h lemel %1$s ha pep tra a zo barzh ? Sur oc\'h lemel an traoù choazet ha pep tra a zo barzh ? E-berzh nemetken - Ur fazi en deus krouet divizoù diemglev ! Ma choazit an daou stumm, ar restr diabarzh en do un niver ouzhpennet war e anv. Skeudenn implijer evit ar roll darempredoù Oaetre ebet roet, netra a zo bet emporzhiet. diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 3f595ad52985..2347b3dd86aa 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -7,7 +7,6 @@ Ha fallat la creació del compte Icona del compte No s\'ha trobat el compte! - Esborra les pujades amb errors Edita Neteja totes les notificacions Buida la paperera @@ -152,7 +151,6 @@ Esteu segur que voleu suprimir %1$s i els seus continguts? Esteu segur que voleu suprimir els elements seleccionats i el seu contingut? Només local - Error creant diàleg de conflicte! Fitxer en conflicte %1$s Fitxer local Si seleccioneu ambdues versions, s\'afegirà un numero al nom del fitxer local. diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 9ede6b4bddbf..68c1ac692513 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -7,7 +7,6 @@ Vytvoření účtu se nezdařilo Ikona účtu Účet nenalezen! - Vyčistit nezdařená nahrávání Upravit Vyčistit všechna upozornění Vyprázdnit koš @@ -43,6 +42,7 @@ Dokončeno Úloha úspěšně smazána Neznámé + Výstup Související účet nenalezen! Přístup se nezdařil: %1$s Účet zatím není na tomto zařízení přidán @@ -157,7 +157,6 @@ Opravdu chcete %1$s a jeho obsah odstranit? Opravdu chcete vybrané položky a jejich obsah odstranit? Pouze místní - Chyba při vytváření dialogu ke konfliktu! Kolidující soubor %1$s Místní soubor Pokud zvolíte obě verze, k názvu místního souboru bude připojeno číslo. diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index f71abf8e69fe..3acb2da04274 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -7,7 +7,6 @@ Fejl ved oprettelse af konto Kontoikon Konto blev ikke fundet. - Fjern fejlede uploads Redigér Ryd alle notifikationer Tøm papirkurv @@ -165,7 +164,6 @@ Er du sikker på at du vil slette %1$s med indhold? Er du sikker på at du vil slette de valgte artikler med indhold? Kun lokal - Fejl ved skabelse af konfliktdialog Fil i konflikt %1$s Lokal fil Hvis du vælger begge versioner, vil den lokale fil få tilføjet et nummer til sit navn. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index bff7d365d391..91c7eab694a8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -7,7 +7,6 @@ Kontoerstellung fehlgeschlagen Konto-Icon Kein Konto gefunden - Fehlgeschlagene Uploads entfernen Bearbeiten Alle Benachrichtigungen löschen Papierkorb leeren @@ -57,6 +56,8 @@ Die Aufgabentypen können nicht abgerufen werden. Bitte überprüfen Sie Ihre Internetverbindung. Assistent Unbekannt + Eingabe + Ausgabe Verknüpftes Konto nicht gefunden! Zugriffsfehler: %1$s Das Konto ist bislang auf dem Gerät nicht vorhanden @@ -171,7 +172,6 @@ Wollen Sie %1$s und deren Inhalte wirklich löschen? Möchten Sie die ausgewählten Elemente und deren inhalt wirklich löschen? Nur lokal - Fehler beim Erstellen des Konfliktdialoges Konflikt-Datei %1$s Lokale Datei Falls beide Versionen gewählt werden, wird bei der lokalen Datei eine Zahl am Ende des Dateinamens hinzugefügt. diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 16962a8c980b..f1be75ab8a5e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -7,7 +7,6 @@ Αποτυχία δημιουργίας λογαριασμού Εικονίδιο λογαριασμού Δεν βρέθηκε λογαριασμός! - Εκκαθάριση αποτυχημένων μεταφορτώσεων Επεξεργασία Εκκαθάριση ειδοποιήσεων Άδειασμα απορριμάτων @@ -151,7 +150,6 @@ Θέλετε σίγουρα να διαγράψετε το %1$s και τα περιεχόμενά του; Θέλετε να διαγράψετε τα επιλεγμένα αντικείμενα και τα περιεχόμενά τους; Μόνο τοπικά - Σφάλμα δημιουργίας αναφοράς διένεξης! Αρχείο σε αντίφαση %1$s Τοπικό αρχείο Εάν επιλέξετε και τις δύο εκδόσεις, στο όνομα του τοπικού αρχείου θα προστεθεί ένας αριθμός. diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index fd216e897d92..dc5eb4c77df6 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -7,7 +7,6 @@ Kreado de konto malsukcesis Konta piktogramo Konto ne trovita! - Vakigi malsukcesajn alŝutojn Modifi Forviŝi ĉiujn sciigojn Malpleni rubujon diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index 743254e1237e..7e55c9bf6eba 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -7,7 +7,6 @@ Falló la creación de la carpeta Icono de cuenta Cuenta no encontrada! - Borrar subidas fallidas Editar Borrar todas las notificaciones Vaciar la papelera @@ -150,7 +149,6 @@ ¿Realmente quieres eliminar %1$s y su contenido? ¿Realmente desea eliminar los elementos seleccionados y sus contenidos? Sólo local - ¡Error al crear el diálogo de conflicto! Archivo en conflicto %1$s Archivo local Si selecciona ambas versiones, se le agregará un número al nombre del archivo copiado. diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index e156f7a25574..65ce9cf03eb5 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -5,7 +5,6 @@ versión %1$s Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Enviar/Compartir Vista de cuadrícula diff --git a/app/src/main/res/values-es-rCO/strings.xml b/app/src/main/res/values-es-rCO/strings.xml index db582242d556..0d6222e01963 100644 --- a/app/src/main/res/values-es-rCO/strings.xml +++ b/app/src/main/res/values-es-rCO/strings.xml @@ -6,7 +6,6 @@ Fallo en la creación de la cuenta Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Borrar todas las notificaciones Vacíar la papelera diff --git a/app/src/main/res/values-es-rCR/strings.xml b/app/src/main/res/values-es-rCR/strings.xml index b1315dd71b0b..d62040810d2b 100644 --- a/app/src/main/res/values-es-rCR/strings.xml +++ b/app/src/main/res/values-es-rCR/strings.xml @@ -5,7 +5,6 @@ versión %1$s Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Enviar/Compartir Vista de cuadrícula diff --git a/app/src/main/res/values-es-rDO/strings.xml b/app/src/main/res/values-es-rDO/strings.xml index 80762f0262a5..2df7ebef158d 100644 --- a/app/src/main/res/values-es-rDO/strings.xml +++ b/app/src/main/res/values-es-rDO/strings.xml @@ -7,7 +7,6 @@ Error al crear la cuenta Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Borrar todas las notificaciones Enviar/Compartir diff --git a/app/src/main/res/values-es-rEC/strings.xml b/app/src/main/res/values-es-rEC/strings.xml index 5e4079a39438..d47f677e77c6 100644 --- a/app/src/main/res/values-es-rEC/strings.xml +++ b/app/src/main/res/values-es-rEC/strings.xml @@ -7,7 +7,6 @@ Creación de cuenta fallida Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Borrar todas las notificaciones Eliminar papelera de reciclaje @@ -153,7 +152,6 @@ ¿Realmente quieres eliminar %1$s y sus contenidos? ¿Reamente deseas eliminar los elementos seleccionados y sus contenidos? Sólo local - ¡Error al crear el diálogo de conflicto! Archivo en conflicto %1$s Archivo local Si selecciona ambas versiones, el archivo local tendrá un número agregado a su nombre. diff --git a/app/src/main/res/values-es-rGT/strings.xml b/app/src/main/res/values-es-rGT/strings.xml index db65d670f3de..fff2dea4f39e 100644 --- a/app/src/main/res/values-es-rGT/strings.xml +++ b/app/src/main/res/values-es-rGT/strings.xml @@ -5,7 +5,6 @@ versión %1$s Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Enviar/Compartir Vista de cuadrícula diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 2854e8c326c9..607f89aa834c 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -7,7 +7,6 @@ Falló la creación de la cuenta Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Limpiar todas las notificaciones Vaciar la papelera de reciclaje @@ -171,7 +170,6 @@ ¿Realmente quieres eliminar %1$s y sus contenidos? ¿Reamente deseas eliminar los elementos seleccionados y sus contenidos? Sólo local - ¡Se presentó un error al crear el diálogo de conflictos! Archivo conflictivo %1$s Archivo local Si seleccionas ambas versiones, el archivo local tendrá un número al final del nombre. diff --git a/app/src/main/res/values-es-rSV/strings.xml b/app/src/main/res/values-es-rSV/strings.xml index b1315dd71b0b..d62040810d2b 100644 --- a/app/src/main/res/values-es-rSV/strings.xml +++ b/app/src/main/res/values-es-rSV/strings.xml @@ -5,7 +5,6 @@ versión %1$s Ícono de la cuenta ¡No se encontró la cuenta! - Borrar cargas fallidas Editar Enviar/Compartir Vista de cuadrícula diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 10f3ec42ef1e..55ad1cdc1843 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -7,7 +7,6 @@ Ha fallado la creación de la cuenta Icono de la cuenta ¡Cuenta no encontrada! - Borrar subidas fallidas Editar Limpiar todas las notificaciones Vaciar papelera @@ -47,6 +46,8 @@ ¡La tarea fue eliminada exitósamente! Eliminar tarea Desconocido + Entrada + Salida ¡Cuenta asociada no encontrada! Acceso fallido: %1$s La cuenta no se ha añadido aún en este dispositivo @@ -160,7 +161,6 @@ ¿Realmente deseas eliminar %1$s y todo su contenido? ¿Estás seguro de que quieres eliminar los elementos seleccionados y sus contenidos? Solo local - ¡Error al crear el diálogo de conflicto! Conflicto en archivo %1$s Archivo local Si seleccionas ambas versiones, el archivo local tendrá un número añadido a su nombre. diff --git a/app/src/main/res/values-et-rEE/strings.xml b/app/src/main/res/values-et-rEE/strings.xml index 3fd7190e6492..bd34acccb120 100644 --- a/app/src/main/res/values-et-rEE/strings.xml +++ b/app/src/main/res/values-et-rEE/strings.xml @@ -7,7 +7,6 @@ Konto loomine ebaõnnestus Konto ikoon Kontot ei leitud! - Puhasta ebaõnnestunud üleslaadimised Redigeeri Kustuta kõik teavitused Tühjenda prügikast @@ -136,7 +135,6 @@ Oled sa kindel, et soovid %1$s ja selle sisu kustutada? Oled sa kindel, et soovid valitud objektid ja nende sisud kustutada? Ainult kohalik - Konfliktidialoogi loomine ebaõnnestus! Kohalik fail Kui valid mõlemad versioonid, siis lisatakse kohaliku faili nimele number. Serveri fail diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 4fdfacf562e3..732363ee662f 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -7,7 +7,6 @@ Kontuaren sorrerak huts egin du Kontuaren ikonoa Ez da kontua aurkitu! - Garbitu huts egin duten igoerak Aldatu Garbitu jakinarazpen guztiak Hustu zakarrontzia @@ -47,6 +46,8 @@ Ezabatu zeregina Morroia Ezezaguna + Sarrera + Irteera Ez da aurkitu lotutako konturik Huts egin du atzitzean: %1$s Kontua ez da gailu honetan gehitu oraindik @@ -161,7 +162,6 @@ Ziur zaude %1$s eta bere edukia ezabatu nahi duzula? Ziur zaude hautatutako elementuak eta beren edukiak ezabatu nahi dituzula? Lokala bakarrik - Errorea gatazkaren elkarrizketa-koadroa sortzean! %1$sfitxategi gatazkatsua Fitxategi lokala Bi bertsioak hautatzen badituzu, fitxategi lokalaren izenari zenbaki bat gehituko zaio. diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index ffa200e71365..a11913415a69 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -7,7 +7,6 @@ ایجاد حساب ناموفق بود آیکون حساب حساب پیدا نشد! - پاک کردن آپلودهای ناموفق ویرایش پاک کردن تمام اعلانها خالی کردن سطل زباله @@ -158,7 +157,6 @@ آیا واقعا می خواهید %1$s و محتویات آن را حذف کنید؟ آیا واقعاً می‌خواهید موارد انتخاب شده و محتوای آنها حذف شود؟ فقط محلی - هنگام ساختن دیالوگ مغایرت‌ها خطایی رخ داده است! فایل متناقض %1$s پروندهٔ محلّی اگر هردو نسخه را انتخاب کنید، یک شماره به نام فایل محلی اضافه خواهد شد. diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 0acc4e060dbc..e68acdc7ad27 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -7,7 +7,6 @@ Tilin luonti epäonnistui Tilikuvake Tiliä ei löydy! - Tyhjennä epäonnistuneet lähetykset Muokkaa Hylkää kaikki ilmoitukset Tyhjennä roskakori @@ -158,7 +157,6 @@ Haluatko varmasti poistaa kohteen %1$s ja sen sisällön? Haluatko varmasti poistaa valitut kohteet ja niiden sisällön? Vain paikallisen - Virhe konfliktitietojen näyttämisessä! Ristiriitainen kohde %1$s Paikallinen tiedosto Jos valitset molemmat versiot, paikallisen tiedoston nimeen lisätään numero. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 363fa1ee4dc9..1370acfc6ae6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -7,7 +7,6 @@ Échec de création du compte Icône du compte Compte introuvable ! - Effacer les téléversements échoués Modifier Effacer toutes les notifications Vider la corbeille @@ -57,6 +56,8 @@ Impossible de récupérer les types des tâches, veuillez vérifier votre connexion Internet. Assistant Inconnu + Entrée + Sortie Compte associé introuvable ! L\'accès a échoué: %1$s Le compte n\'est pas encore ajouté sur cet appareil @@ -171,7 +172,6 @@ Voulez-vous vraiment supprimer %1$s et ses contenus ? Souhaitez-vous vraiment supprimer les éléments sélectionnés ainsi que leurs contenus ? Local seulement - Une erreur qui crée un dialogue conflictuel ! Fichier %1$s en conflit fichier local Si vous sélectionnez les deux versions, le fichier local aura un numéro ajouté à son nom. diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml index cafc2e6030f8..0782068f8dab 100644 --- a/app/src/main/res/values-gd/strings.xml +++ b/app/src/main/res/values-gd/strings.xml @@ -7,7 +7,6 @@ Dh’fhàillig cruthachadh a’ chunntais Ìomhaigheag a’ chunntais Cha deach an cunntas a lorg! - Falamhaich na luchdaidhean suas a dh’fhàillig Deasaich Falamhaich a h-uile brath Falamhaich an sgudal @@ -138,7 +137,6 @@ A bheil thu cinnteach gu bheil thu airson %1$s ’s a shusbaint a sguabadh às? A bheil thu cinnteach gu bheil thu airson na nithean a thagh thu ’s an susbaint a sguabadh às? Ionadail a-mhàin - Mearachd le cruthachadh còmhradh na còmhstri! Faidhle %1$s ann an còmhstri Ma thaghas tu an dà thionndadh, thèid àireamh a chur ri ainm an fhaidhle ionadail. Ìomhaigheag a’ chleachdaiche air liosta an luchd-aithne diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 78bc6ce05b75..372563b1986a 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -7,7 +7,6 @@ Produciuse un fallo ao crear a conta Icona da conta Non se atopou a conta! - Limpar os envíos fallados Editar Limpar todas as notificacións Baleirar o lixo @@ -43,6 +42,7 @@ Completado A tarefa foi eliminada satisfactoriamente Descoñecido + Entrada Non se atopou unha conta asociada! Acceso fallado: %1$s A conta aínda non existe no dispositivo @@ -155,7 +155,6 @@ Confirma que quere eliminar %1$s e todo o seu contido? Confirma que quere eliminar os elementos seleccionados e o seu contido? Só local - Produciuse un erro ao crear o diálogo de conflitos! Ficheiro en conflito %1$s Ficheiro local Se selecciona ambas versións, o ficheiro local terá un número engadido ao nome. diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 1ceb37ce3032..c4dad0a47fd5 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -7,7 +7,6 @@ Kreiranje korisničkog računa neuspjelo Ikona korisničkog računa Korisnički račun nije pronađen! - Izbriši neuspješne otpreme Uredi Izbriši sve obavijesti Isprazni kantu za smeće @@ -145,7 +144,6 @@ Želite li zaista izbrisati %1$s i pripadajući sadržaj? Želite li zaista izbrisati odabrane stavke i pripadajući sadržaj? Samo lokalno - Pogreška pri stvaranju dijaloškog okvira o nepodudaranju! Nepodudarna datoteka %1$s Lokalna datoteka Ako odaberete obje inačice, lokalna će datoteka uz naziv imati i broj. diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index f78a9c10e7ad..3e2123ce5724 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -7,7 +7,6 @@ A fiók létrehozása sikertelen Fiók ikon A fiók nem található! - Sikertelen feltöltések eltávolítása Szerkesztés Összes értesítés törlése Kuka ürítése @@ -155,7 +154,6 @@ Biztos, hogy törli ezt: %1$s és a tartalmát? Biztos, hogy törli a kiválasztott elemeket és tartalmukat? Csak a helyi példány - Hiba az ütközési párbeszédablak létrehozásakor! Ütköző fájl: %1$s Helyi fájl Amennyiben mindkét verziót kiválasztja, a helyi fájl nevéhez egy szám lesz hozzáfűzve. diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index bd58c42484f5..2fbc92625e05 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -7,7 +7,6 @@ Pembuatan akun gagal Ikon akun Akun tidak ditemukan! - Bersihkan unggahan gagal. Sunting Hapus semua notifikasi Kosongkan tempat sampah @@ -147,7 +146,6 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Apakah anda yakin ingin menghapus %1$s beserta isinya? Apa anda yakin ingin menghapus item yang terpilih beserta isinya? Lokal saja - Galat saat membuat dialog konflik! File konflik %1$s File lokal Jika Anda memilih kedua versi, nama dari berkas lokal akan ditambahi angka. diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 8c96737ff070..74c49d144cf2 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -7,7 +7,6 @@ Gerð notandaaðgangs mistókst Táknmynd fyrir notandaaðgang Notandaaðgangur fannst ekki! - Hreinsa lista yfir innsendingar sem mistókust Breyta Hreinsa allar tilkynningar Tæma ruslið @@ -150,7 +149,6 @@ Ertu viss um að þú viljir eyða %1$s og innihaldi þess? Ertu viss um að þú viljir eyða völdum atriðum og innihaldi þeirra? Einungis staðvært - Villa við að búa til árekstraglugga! Skrá á tölvunni Ef þú velur báðar útgáfur, þá mun verða bætt tölustaf aftan við heiti afrituðu skrárinnar. Skrá á netþjóni diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index cb8efdebdedc..bdcc76abb7c3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -7,7 +7,6 @@ Creazione dell\'account non riuscita Icona dell\'account Account non trovato - Cancella caricamenti non riusciti Modifica Cancella tutte le notifiche Svuota cestino @@ -153,7 +152,6 @@ Vuoi davvero rimuovere %1$s e il relativo contenuto? Vuoi davvero eliminare gli elementi selezionati e il loro contenuto? Solo localmente - Errore di creazione della finestra di conflitto! File %1$s in conflitto File locale Se selezioni entrambe le versioni, il file locale ha un numero aggiunto al suo nome. diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index db059895baac..5def87a8eecb 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -7,7 +7,6 @@ יצירת החשבון נכשלה סמל חשבון החשבון לא נמצא! - פינוי העלאות שנכשלו עריכה פינוי כל ההתראות פינוי סל האשפה @@ -144,7 +143,6 @@ למחוק את %1$s על תוכנו? למחוק את הפריטים הנבחרים ואת תוכנם? מקומי בלבד - שגיאה ביצירת תיבת דו־שיח סתירה! קובץ מקומי בבחירה של שתי הגרסאות, יתווסף מספר בסוף שמו של הקובץ המקומי. קובץ בשרת diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index fe5368775ec3..30c83eff3f99 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -7,7 +7,6 @@ アカウントの作成に失敗しました アカウントアイコン アカウントが見つかりません! - 失敗したアップロードのクリア 編集 全ての通知を削除 ゴミ箱を空にする @@ -155,7 +154,6 @@ 本当に %1$s を中身も一緒に削除しますか? 本当に選択したアイテムとその内容を削除しますか? ローカルのみ - コンフリクトダイアログの作成に失敗しました %1$sはすでに存在します ローカルファイル 両方のバージョンを選択した場合、ローカルファイルはファイル名に数字が追加されます。 diff --git a/app/src/main/res/values-ka-rGE/strings.xml b/app/src/main/res/values-ka-rGE/strings.xml deleted file mode 100644 index 01b6281dccd1..000000000000 --- a/app/src/main/res/values-ka-rGE/strings.xml +++ /dev/null @@ -1,506 +0,0 @@ - - - %1$s Android აპლიკაცია - ჩვენს შესახებ - ვერსია %1$s - ანგარიშის პიქტოგრამა - ანგარიში ვერ იქნა ნაპოვნი! - წარუმატებლად დასრულებული ატვირთების გასუფთავება - ცვლილება - გაგზავნა/გაზიარება - ბადისებური ხედი - ჩამონათვლისებური ხედი - ახალი დირექტორია - გახსნა - ძიება - დეტალები - გაგზავნა - პარამეტრები - განლაგება - აქტიური მომხმარებელი - აქტოვობა ჯერ არაა - გაგზავნა - გააგზავნეთ ბმული… - აქტივობა - ხელახალი გაზიარების დაშვება - ყველა - ანგარიში ამ მოწყობილობაზე ჯერ არაა დამატებული - მოწყობილობაზე ანგარიში ამ მომხმარებლით და სერვერით უკვე არსებობს - შეყვანილი მომხმარებელი არ ემთხვევა ამ ანგარიშის მომხმარებელს - სერვერის ამოუცნობი ვერსია - კავშირი დამყარდა - სერვერის მისამართი https://... - სერვერისთვის არასწორი მისამსამართის ფორმატი - სერვერი ვერ მოიძებნა - ქსელთან კავშირი არ არის - დაცული კავშირი არაა ხელმისაწვდომი. - არასწორი სერვერის კონფიგურაცია - წარუმატებელი ავტორიზაცია - წვდომა ავტორიზაციის სერვერის მიერ აიკრძალა - დაცული კავშირი გადამისამართდა დაუცველი მარშრუტით. - დაცული კავშირი დამყარდა - SSL ინიციალიზაცია ვერ მოხერხდა - SSL სერვერის იდენტობა ვერ დამოწმდა - კავშირის შემოწმება - სერვერმა პასუხი დააგვიანია - არასწორი მომხმარებელი ან პაროლი - წარმოიშვა უცნობი შეცდომა! - ჰოსტი ვერ მოიძებნა - %1$s არ უჭერს მხარს მრავალი ანგარიშის არსებობას - კავშირი ვერ დამყარდა - ატვირთვა მხოლოდ შეუზღუდავ Wi-Fi-ზე - /ავტომატური_ატვირთვა - შექმენით ახალი სპეციფიური დირექტორია - დააყენეთ სპეციფიური დირექტორია - ავატარი - დახურვა - გამორთვა - კალენდარი - სერტიპიკატის ჩატვირთვასთან პრობლემაა. - ჩექბოქსი - ტექსტი %1$s-იდან დაკოპირდა - ბუფერში გადასატანად ტექსტი მიღებული არაა - ბუფერში გადატანისას წარმოშვა მოულოდნელი შეცდომა - უკან - გაუქმება - სინქრონიზაციის შეჩერება - აირჩიეთ ანგარიში - დადასტურება - კოპირება - გაუქმება - შეცდომა - არასაკმარისი მეხსიერება - უცნობი შეცდომა - იტვირთება… - შემდეგი - არა - კარგი - მოლოდინშია - გაუქმება - გადარქმევა - შენახვა - გაგზავნა - გაზიარება - გამოტოვება - კი - დევ. ვერსიის შემოწმება - იმყოფება სისხლდენის ზღვარზე და მოიცავს ყველა დამდეგ ფუნქციას. შეიძლება გამოჩნდეს შეცდომები, ასეთი შემთხვევისას გთხოვთ გვამცნობოთ რეპორტით. - ფურუმი - დაეხმარეთ სხვებს - აქტიურად შეიტანეთ წვლილი - აპლიკაცია - გადათარგმნეთ - დეველოპმენტ რელიზის პირდაპირი ჩამოტვირთვა - მიიღეთ დეველოპმენტ რელიზი F-Droid აპლიკაციიდან - მიიღეთ რელიზ კანდიდატი F-Droid აპლიკაციიდან - მიიღეთ რელიზ კანდიდატი Google Play-დან - რელიზის კანდიდატი - ეს რელიზის კანდიდატი (რკ) დამდეგი რელიზის კადრია და მოსალოდნელია მისი სტაბილურობა. ამის დამოწმებაში დაგვეხმარება ინდივიდუალური მოწყობილობის შემოწმება. შემოწმებისთვის დარეგისტრირდით Play-ზე ან გადახედეთ \"ვერსიის\" სექციას F-Droid-ში. - იპოვეთ შეცდომა? უცნაურობა? - დაგვეხმარეთ შემოწმებით - დაამატეთ მოხსენიება GitHub-ზე - ნამდვილად გსურთ %1$s-ის გაუქმება? - დარწმუნებული ხართ, რომ გსურთ არჩეული ჩანაწერების გაუქმება? - ნამდვილად გსურთ %1$s-ის და შემცველობის გაუქმება? - დარწმუნებული ხართ, რომ გსურთ არჩეული ჩანაწერებისა და მათი შემცველობის გაუქმება? - მხოლოდ ლოკალური - მომხმარებლის პიქტოგრამა კონტაქტების სიისთვის - უფლებები არაა მოცემული, არაფერი არ იქნა იმპორტირებული. - კონტაქტები - ახალი ბექაფი - ბექაფი დაინიშნა და მალე დაიწყება - იმპორტი დაინიშნა და მალე დაიწყება - ფაილი ვერ იქნა ნაპოვნი - თქვენი ბოლო ბექაფი ვერ იქნა ნაპოვნი! - კოპირებულია კლიპბორდში - ამ ფაილისა თუ დირექტორიის კოპირებისას წარმოიშვა შეცდომა - დირექტორიის კოპირება მასში არსებულ დირექტორიაში შეუძლებელია - ფაილი დანიშნულ დირექტორიაში უკვე არსებობს - ბმულის კოპირება - ამჟამად კოპირება/გადატანა დაშიფრულ დირექტორიაში არაა მხარდაჭერილი. - შექმნა - დირექტორია ვერ შეიქმნა - ანგარიშის გაუქმება - ყველას წაშლა - ხელმისაწვდომია ახალი ვერსია - ახალი ვერსია არაა ხელმისაწვდომი. - დახურვა - თქვენს ტელეფონს ამ ალგორითმის დაიჯესტის მხარდაჭერა არ აქვს. - გამორთვა - დათხოვნა - დასრულებულია - ვერ ჩამოიტვირთა %1$s - ჩამოტვირთვა ვერ მოხერხდა, ახლიდან გაიარეთ ავტორიზაცია - ჩამოტვირთვა ვერ განხორციელდა - ფაილი სერვერზე ხელმისაწვდომი აღარაა - %1$d%% ჩამოტვირთვა %2$s - %1$s ჩამოტვირთლია - ჩამოტვირთულია - ჯერ ვერ ჩამოიტვირთა - მხაზველი დასათაურების ფონური სურათი - აქტივობები - ყველა ფაილი - რჩეულები - სახლი - შეტყობინებები - მოწყობილობაზე - ახლად შეცვლილი - გაზიარებული - გაუქმებული ფაილები - ატვირთვები - გასვლა - გამოყენებულია %1$s სულ %2$s-იდან  - ავტო-ატვირთვა - უფრო მეტი - ჩანაწერები - საუბარი - დააყენეთ როგორც დაშიფრული - შიფრაციის დაყენება - დახურვა - პირადი გასაღების დეშიფრაციისთვის გთხოვთ შეიყვანოთ პაროლი. - ეს დირექტორია არაა ცარიელი - 12 სიტყვა ერთად წარმოქმნის ძალიან ძლიერ პაროლს, იძლევა თქვენი დაშიფრული ფაილების ჩვენებისა და მოხმარების უფლებას. გთხოვთ ჩაიწეროთ და შეინახოთ დაცულ ადგილას. - შენიშნეთ თქვენი 12 სიტყვიანი შიფრაციის პაროლი - გასაღებების შენახვა - შიფრაციის დაყენება - გასაღებების შენახვა ვერ მოხერხდა, გთხოვთ სცადოთ ახლიდან. - შეცდომა დეშიფრაციისას. არასწორი პაროლი? - %1$s ვერ კოპირდება %2$s ლოკალურ დირექტორიაში - კრიტიკული შეცდომა: ოპერაციების განხორციელება შეუძლებელია - ანგარიშები - შექმნილია - მომხმარებელი - ფონური საქმეები - ჩამოტვირთვა - ატვირთვა - რჩეულებში დამატება - რჩეული - წაშლა - ფაილი - ატვირთეთ რამე ან გაუწიეთ თქვნს მოწყობილობას სინქრონიზაცია. - რჩეულებში ჯერ არაფერი დამატებულია - აქ ფაილები არაა - ამ დირექტორიაში შედეგები არაა - შედეგები არაა - აქ არაფერია. შეგიძლიათ დაამატოთ დირექტორია. - გასული 7 დღის განმავლობაში შეცვლილი ფაილ(ებ)ი ვერ იქნა ნაპოვნი - იქნებ სხვა დირექტორიაშია? - ჯერ არაფერი გაზიარებულა - დირექტორია - იტვირთება… - ამ ფაილთან სამუშაოდ არც ერთი აპლიკაცია არაა დაყანებული. - წამის წინ - მონაცემების დირექტორია უკვე არსებობს. აირჩიეთ ერთ-ერთი შემდეგიდან: - Nextcloud დირექტორია უკვე არსებობს - საჭიროა მეტი სივრცე - წყარო-ფაილის წაკითხვა ვერ მოხერხდა - სამიზნე ფაილში ჩაწერა ვერ მოხერხდა - მიგრაციისას წარმოიქმნა შეცდომა - ინდექსის განახლება ვერ მოხერხდა - დასრულებულია - ჩანაცვლება - წყარო-დირექტორია ვერ იკითხება! - მოხმარება - ფაილი ვერ იქნა ნაპოვნი - ფაილის სინქ ვერ მოხერხდა. ნაჩვენებია ბოლო ხელმისაწვდომი ვარიანტი. - სახელის შეცვლა - დეტალები - ჩამოტვირთვა - ექსპორტი - ატვირთვისას ფაილს სახელი შეეცვალა %1$s-ზე - სინქ - ფაილი არაა არჩეული - ფაილის სახელი ვერ იქნება ცარიელი - აკრძალული ნიშნები: / \\ < > : \" | ? * - ფაილის სახელი შეიცავს მინ. 1 არასწორ ნიშანს - ფაილის სახელი - შექმნა - აქ დირექტორიები არაა - აირჩიეთ - გადატანა - თქვენ არ გაქვთ უფლება, %s - რომ დააკოპიროთ ეს ფაილი - შექმნათ ეს ფაილი - გააუქმოთ ეს ფაილი - რომ გადაიტანოთ ეს ფაილი - შეუცვალოთ ამ ფაილს სახელი - ფაილების ატვირთვა... - გარკვეული ფაილების გადატანა ვერ მოხერხდა - ლოკალური: %1$s - ყველას გადატანა - დისტანციური: %1$s - ყველა ფაილი გადატანილია - წინ - 4 საათი - სახელი - პაროლი - ატვირთვა მხოლოდ დატენვისას - /მყისიერი_ატვირთვა - უჩინარი - ბმული - ატვირთვისა და ცვლილების უფლებების მინიჭება - ფაილის ჩაგდება (მხოლოდ ატვირთვა) - ჩამოწერილი მაკეტი - ამ დირექტორიაში ფაილები არაა. - ლოკალურ ფაილ-სისტემაში ფაილი ვერ მოიძებნა - მომდევნო დირექტორიები არაა. - %1$s Android აპლიკაციის ლოგები. - ლოგინი - განახლება - იტვირთება… - ლოგები - მონაცემების გასუფთავება -  %1$s-ის მონაცემებიდან პარამეტრები, მონაცემთა ბაზა და სერტიფიკატები სამუდამოდ წაიშლება.\n\nგადმოწერილი ფაილები დარჩება ხელუხლებელი.\n\nეს პროცესი გასტანს გარკვეულ დროს. - მოცულობის მენეჯმენტი - მედია ფაილის წაკითხვა ვერ მოხერხდა - მედია ფაილს გააჩნია არასწორი კოდირება - ფაილის დაკვრის მცდელობის დრო ამოიწურა - ჩაშენებული მედია დამკვრელი ვერ უკრავს მედია ფაილს - მედია კოდეკი მხარდაუჭერელია - სწრაფი გადახვევის ღილაკი - %1$s მუსიკის დამკვრელი - დაკვრის ან პაუზის ღილაკი - გადახვევის ღილაკი - %1$s (იკვრება) - ჯერ ახალი - ჯერ ძველი - ა - ჰ - ჰ - ა - ჯერ დიდი - ჯერ პატარა - მეტი - ამ ფაილისა თუ დირექტორიის გადატანისას წარმოიშვა შეცდომა - დირექტორიის გადატანა მასში არსებულ დირექტორიაში შეუძლებელია - ფაილი დანიშნულ დირექტორიაში უკვე არსებობს - სერვერთან დაკავშირებისას წარმოიქმნა შეცდომა - ფოტო - აჩვენებს გადმოწერის პროგრესს - ჩამოტვირთვები - აჩვენებს ფაილების სინქ. პროგრესს და შედეგებს - ფაილების სინქ. - მუსიკის დამკვრელის პროგრესი - მედია დამკვრელი - აჩვენებს ატვირთვის პროგრესს - ატვირთვები - შეტყობინებები არაა - გთხოვთ დაბრუნდეთ მოგვინაებით. - 1 საათი - შეიყვანეთ თქვენი პასკოდი - პასკოდი მოთხოვნილ იქნება აპლიკაციის ყოველი გაშვებისას - გთხოვთ შეიყვანოთ თქვენი პასკოდი - პასკოდები ერთმანეთს არ ემთხვევა - გთხოვთ თქვენი პასკოდი შეიყვანოთ ახლიდან - თქვენი პასკოდის გაუქმება - პასკოდი გაუქმდა - პასკოდი შენახულია - არასწორი პასკოდი - ფაილების ატვირთვისა და გადმოწერისათვის საჭიროა დამატებითი უფლებები. - სურათის დასაყენებლად ვერც ერთი აპლიკაცია ვერ იქნა ნაპოვნი - 389 კბ - ადგილი.txt - 12:23:45 - ეს არის ადგილი - 18/05/2012 12:23 - გაუქმებულია - დარჩა ორიგინალ დირექტორიაში - გადატანილია აპლიკაციის დირექტორიაში - ანგარიშის დამატება - არც Google Play-ა დაყენებული, არც F-Droid-ი - ჩვენს შესახებ - დეტალები - დევ. - ზოგადი - მეტი - კონტაქტების ყოველდღიური ბექაფი - GNU ზოგადი ღია ლიცენზია, ვერსია 2 - დახმარება - ბეჭედი - ქვე-დირექტორიების მოხმარება - ლიცენზია - არც ერთი - ანგარიშების მართვა - დამალული ფაილების ჩვენება - მიიღეთ კოდი - ლოკალური დირექტორია - დისტანციური დირექტორია - ვიზუალური თემა - მუქი - ღია - სურათის წინასწარი ჩვენება - წინასწარი ჩვენებისთვის ლოკალური ფაილი არაა - სურათის ჩვენება შეუძლებელია - ბოდიში - კონფიდენციალურობა - Google Play სერვისების მესაკუთრეობრივი დამოკიდებულებების გამო, ფუშ შეტყობინებები გათიშულია. - ვადაგასული აუტენტიფიკაციის გამო ფუშ შეტყობინებები არაა. გთხოვთ გაითვალისწინოთ თქვენი ანგარიშის თავიდან დამატება. - ფუშ შეტყობინებები ამჟამად ხელმიუწვდომელია. - სცდეთ %1$s თქვენს მოწყობილობაზე! - გიწვევთ გამოიყენოთ %1$s თქვენს მოწყობილობაზე.\nჩამოტვირთეთ აქედან: %2$s - %1$s ან %2$s - გადატვირთვა - გაუქმება ვერ მოხერხდა - გაუქმება - გაუქმდა - შეიყვანეთ ახალი სახელი - ლოკალური ასლის სახელის გადარქმევა ვერ მოხერხდა, სცადეთ სხვა სახელი - გადარქმევა შეუძლებელია, სახელი უკვე დაკავებულია - ხელახალი გაზიარება არაა დაშვებული - ხელახალი გაზიარება არაა ნებადართული - ზომა-შეცვლილი სურათი არაა ხელმისაწვდომი. გადმოვწეროთ მთლიანი სურათი? - ყველას მონიშვნა - გაგზავნა - დააყენეთ როგორც - გამოიყენეთ სურათი როგორც - გაზიარება - გაზიარება - %1$s-ის გაზიარება - %1$s (ჯგუფი) - ბმულის გაზიარება - უნდა შეიყვანოთ პაროლი - გააზიაროთ ეს ფაილი - შეიყვანეთ პაროლი - მიუთითეთ ვადის გასვლის დრო - პაროლის დაყენება - შეუძლია შეცვალოს - %1$s (დისტანციური) - პარამეტრები - ბმულის გაზიარება - გაზიარებული - დაასორტირე - დამალვა - დეტალები - სერვერის იდენტურობა ვერ დამოწმდა - ქვეყანა: - ზოგადი სახელი: - ადგილმდებარეობა: - ორგანიზაცია: - ორგანიზაციის განყოფილება: - შტატი: - თითის ანაბეჭდი: - გაცემულია მიერ: - ხელმოწერა: - ალგორითმი: - გაცემულია: - მოქმედების ვადა: - ვისგან: - ვის: - - ამ შეცდომაზე ინფორმაცია არაა - სერტიფიკატის შენახვა ვერ მოხერხდა - სერტიფიკატის ჩვენება შეუძლებელია. - გსურთ მაინც ენდოთ ამ სერტიფიკატს? - - სერვერის სერტიფიკატი ვადაგასულია - - სერვერის სერტიფიკატი არ არის სანდო - - სერვერის სერტიფიკატის თარიღები მომავალშია - - URL არ ემთხვევა სერტიფიკატში არსებულ ჰოსტნეიმს - საწყისი - ჩამოტვირთვები - გაგიზიარდათ \"%1$s\" - %1$s-სგან გაგიზიარდათ \"%2$s\" - წარმოიშვა კონფლიქტი - დირექტორია %1$s აღარ არსებობს - %1$s სინქ ვერ მოხერხდა - %1$s რესურსის არასწორი პაროლი - Kept-in-sync ფაილების შეცდომა - სინქრონიზაცია დასრუდლა წარუმატებლად - სინქ ვერ მოხერხდა, ახლიდან გაიარეთ ავტორიზაცია - ფაილების შემცველობა სინქრონიზირებულია - როდესაც ერთი ფაილი სინქრონიზირებულია რამოდენიმე ანგარიშთან, 1.3.16 ვერსიაში მონაცემების დაკარგვისგან თავის ასარიდებლად, ამ მოწყობილობით ატვირთული ფაილ(ებ)ი კოპირდება %1$s დირექტორიაში.\n\nამ ცვლილების გამო, აპლიკაციის ძველი ვერსიით ატვირთული ყველა ფაილი დაკოპირდა %2$s დირექტორიაში. თუმცა, შეცდომის გამო სინქრონიზაციისას მოხდა ამ ოპერაციის შეჩერება. შეგიძლიათ ფაილ(ებ)ი დატოვოთ ისე როგორც არის და წაშალოთ ბმული %3$s-სთან, ან გადაიტანოთ ფაილ(ებ)ი %1$s დირექტორიაში და შეინარჩუნოთ ბმული %4$s-ისთვის.\n\nქვემოთ ჩამოწერილია ლოკალური და %5$s-ში არსებული დისტანციური ფაილ(ებ)ი. - რამოდენიმე ლოკალური ფაილი გამორჩენილია - ამოღებულია ფაილის უახლესი ვერსია. - სინქ. სტატუსის ღილაკი - ფაილები - პარამეტრების ღილაკი - დირექტორიების კონფიგურაცია - მყისიერი ატვირთვა სრულიად გამოსწორდა. ავტო-ატვირთვას რეკონფიგურაცია გაუწიეთ მთავარი მენიუდან.\n\nისიამოვნეთ ახალი და გაუმჯობესებული ავტო-ატვირთვით. - %1$s-ისთვის - სახეობა - ტეგები - სერვერთან კავშირის შემოწმება - 30 წუთი - ამ კვირაში - მინიატურა - დღეს - გაუქმებული ფაილები - წაშლილი ფაილები ვერ მოიძებნა - სამუდამოდ წაშლა - შიფრაციის გაუქმება - შეწყვიტოთ ამ ფაილის გაზიარება - წვდომა არასანდო დომენით. დამატებითი ინფორმაციისთვის გთხოვთ იხილოთ დოკუმენტაცია. - განაახლოთ ეს გაზიარება - წარუმატებლად დასრულებული ატვირთების გასუფთავება - წარუმატებლად დასრულებული ატვირთების ხელახლა გაშვება - ფაილის სახელი - ფაილის სახეობა - Google Maps იარლიყის ფაილი(%s) - ინტერნეტ იარლიყის ფაილი(%s) - ტექსტ ფაილის ჩამონაჭერი(.txt) - ატვირთვისთვის შეიყვანეთ ფაილის სახელი და სახეობა - ფაილების ატვირთვა - ელემენტის ატვირთვის ქმედების ღილაკი - წაშლა - არც ერთი ატვირთვა არაა ხელმისაწვდომი. - ატვირთეთ რაიმე ან გაააქტიურეთ ავტო-ატვირთვა. - არასაკმარისი ადგილი აფერხებს არჩეული ფაილების კოპირებას %1$s დირექტორიაში. გსურთ სანაცვლოდ მათი გადატანა? - უცნობი შეცდომა - აირჩიეთ - ატვირთვა - მიღებული მონაცემები არ მოიცავდნენ სწორ ფაილს. - %1$s მომხმარებელს არ აქვს უფლება წაიკითხოს ფაილი. - ფაილის ასლი დროებით დირექტორიაში ვერ შეიქმნა. სცადეთ მისი ახლიდან გაგზავნა. - ატვირთვისთვის არჩეული ფაილი ვერ იქნა ნაპოვნი. გთხოვთ დაამოწმოთ ფაილის არსებობა. - ფაილი ატვირთვისთვის არაა - დირექტორიის სახელი - აირჩიეთ ატვირთვის დირექტორია - %1$s ვერ აიტვირთა - ატვირთვა ვერ მოხერხდა, ახლიდან გაიარეთ ავტორიზაცია - ატვირთვა ვერ განხორციელდა - ატვირთვის ოპციონი: - ფაილის საწყის დირექტორიაში დატოვება - ფაილის საწყისი დირექტორიიდან გაუქმება - ატვირთოთ ამ დირექტორიაში - %1$d%% ატვირთვა %2$s - იტვირთება... - ატვირთულია %1$s - გამოსვლა - დაყენება - ანგარიშები %1$s თქვენს მოწყობილობაზე არაა. გთხოვთ დააყენოთ ანგარიში. - ანგარიში ვერ მოიძებნა - მიმდინარე - ვერ მოხერხებული/მიმდინარე რესტარტი - ატვირთულია - უარყოფილია - ველოდებით ატვირთვას - ატვირთვები - უარყოფილია - კონფლიქტი - კავშირის პრობლემა - შეცდომა უფლებამოსილებებში - ფაილის შეცდომა - დირექტორიის შეცდომა - ლოკალური ფაილი ვერ იქნა ნაპოვნი - შეცდომა უფლებებში - სერვერის არასანდო სერტიფიკატი - აპლიკაცია შეჩერდა - დასრულებულია - უცნობი შეცდომა - ველოდებით ეკონომიური რეჟიმიდან გამოსვლას - გადახდის მოლოდინშია - მომხმარებელი - მისამართი - ელ-ფოსტა - ტელეფონის ნომერი - Twitter-ი - ვებ-საიტი - მოხმარებლის ინფორმაციის მიღებისას წარმოიშვა შეცდომა - პირადი ინფორმაციის კომპლექტი არაა - დაამატეთ სახელი, ფოტო და საკონტაქტო დეტალები თქვენს პროფილის გვერდზე. - მომხმარებლის სახელი - ჩამოტვირთვა - მოწმდება შენახული უფლებამოსილებანი - ფაილის კოპირება პირადი საცავიდან - განახლება - რა არის ახალი სურათი - გამოტოვება - ახალი %1$s-ში - ელ-წერილის გაგზავნა - diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index ed840d85695c..7f19cbf06a14 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -7,7 +7,6 @@ Account creation failed Account icon Account not found! - Clear failed uploads Edit Clear all notifications Empty trash bin @@ -152,7 +151,6 @@ Do you really want to delete %1$s and the contents thereof? Do you really want to delete the selected items and their contents? Local only - Error creating conflict dialog! Conflicting file %1$s Local file If you select both versions, the local file will have a number appended to its name. diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 7c7d534b456e..30781f711852 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -7,7 +7,6 @@ 계정 생성에 실패했습니다. 계정 아이콘 계정을 찾을 수 없습니다! - 실패한 업로드 삭제 편집 모든 알림 지우기 휴지통 비우기 @@ -154,7 +153,6 @@ %1$s 및 포함된 모든 내용을 삭제하시겠습니까? 선택한 항목과 포함된 내용을 삭제하시겠습니까? 로컬만 - 다이얼로그의 충돌로 인한 오류 충돌하는 파일 %1$s 로컬 파일 두 버전을 모두 선택하면 기존 파일 이름에 번호가 추가됩니다. diff --git a/app/src/main/res/values-lo/strings.xml b/app/src/main/res/values-lo/strings.xml index 11b73771ac0f..39cda0df6250 100644 --- a/app/src/main/res/values-lo/strings.xml +++ b/app/src/main/res/values-lo/strings.xml @@ -7,7 +7,6 @@ ການສ້າງບັນຊີບໍ່ສຳເລັດ ໄອຄອນບັນຊີ ບໍ່ພົບບັນຊີ! - ການອັບໂຫຼດບໍ່ສຳເລັດ ແກ້ໄຂ ລ້າງການແຈ້ງເຕືອນທັງຫມົດ ລ້າງຖັງຂີ້ເຫຍື່ອ @@ -145,7 +144,6 @@ ທ່ານຕ້ອງການ ລຶບ%1$s ແລະ ເນື້ອຫາບໍ? ທ່ານຕ້ອງການລຶບລາຍການທີ່ເລືອກ ແລະ ເນື້ອຫາແທ້ບໍ? ຊ່ອງເກັບຢ່າງດຽວ - ຄວາມຜິດພາດໃນການສ້າງການສົນທະນາຜິດພາດ! ຟາຍຜິດພາດ%1$s ຖ້າທ່ານເລືອກເອົາທັງສອງເວີຊັ້ນ, ບ່ອນເກັບຟາຍຈະມີຈໍານວນສະສົມ ລາຍການໄອຄອນຜູ້ຕິດຕໍ່ diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index eccaac995f54..24ddd93adb37 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -7,7 +7,6 @@ Paskyros sukūrimas nepavyko Paskyros piktograma Paskyra nerasta! - Išvalyti nepavykusius įkėlimus Taisyti Išvalyti visus pranešimus Išvalyti šiukšlinę @@ -147,7 +146,6 @@ Ar tikrai norite ištrinti %1$s ir jo turinį? Ar tikrai norite ištrinti pažymėtus elementus ir jų turinį? Tik vietiniai - Klaida kuriant konflikto dialogą! Nesuderinamas failas%1$s Vietinis failas Jei pasirinksite abi versijas, vietinis failas prie pavadinimo turės numerį. diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index f7debdce83cf..080f09398c09 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -7,7 +7,6 @@ Konta izveidošana neizdevās Konta ikona Konts nav atrasts! - Notīrīt neizdevušās augšupielādes Rediģēt Notīrīt visus paziņojumus Izdzēst miskastes saturu @@ -123,7 +122,6 @@ Vai tiešām vēlaties izdzēst %1$s un tā saturu? Vai tiešām vēlies dzēst izvēlētos objektus un to saturu? Tikai lokālos - Kļūda veidojot konfliktu dialogu! Lietotāja ikona kontaktpersonu sarakstam Nav dota atļauja, importēšana neizdevās Kontakti diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index f9d63cdeaf2c..bea766436061 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -7,7 +7,6 @@ Неуспешно креирање на сметка Икона за сметката Сметката не е пројандена! - Исчисти ги неуспешните прикачувања Уреди Исчисти ги сите известувања Испразни ја корпата со отпадоци @@ -144,7 +143,6 @@ али си сигурен дека сакаш да ја избришеш %1$s и содржината во истата? Дали си сигурен дека сакаш да ја избришеш означената ставкаи содржината во неа? Само локално - Грешка при креирање конфликтен извештај! Датотеки со конфликт %1$s Локална датотека Ако ги одберете и двете верзии, локалната датотека ќе има број додаден на нејзиното име. diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 5274e2b33061..a97cedbda070 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -7,7 +7,6 @@ Oppretting av konto mislyktes Kontoikon Konto ble ikke funnet! - Fjern feilede opplastinger Rediger Slett alle varsel Tøm papirkurv @@ -57,6 +56,8 @@ Kan ikke hente oppgavetyper, vennligst sjekk internettforbindelsen din. Assistent Ukjent + Inndata + Utdata Tilknyttet bruker ikke funnet! Tilgang mislyktes: %1$s Kontoen er ikke lagt til på denne enheten enda @@ -171,7 +172,6 @@ Ønsker du virkelig å slette %1$s og dets innhold? Vil du virkelig fjerne de valgte elementene og dets innhold? Kun lokalt - Feil ved oppretting av konfliktdialog! Konflikt med%1$s Lokal fil Hvis du velger begge versjonene vil den lokale filen få et tall lagt til på slutten av navnet. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 7c997db67bb6..764a6aaa871b 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -7,7 +7,6 @@ Account aanmaken mislukt Accountpictogram Account niet gevonden! - Wis mislukte uploads Bewerken Handel alle meldingen af Prullenbak legen @@ -167,7 +166,6 @@ Wil je %1$s en de inhoud ervan werkelijk verwijderen? Wil je de geselecteerde objecten en hun inhoud echt verwijderen? Alleen lokaal - Fout bij het maken van conflictdialoog! Conflicterend bestand%1$s Lokaal bestand Als je beide versies selecteert, zal het lokale bestand een nummer aan de naam toegevoegd krijgen. diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 417fdfa52d8b..78f1f38430cd 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -7,7 +7,6 @@ Błąd tworzenia konta Ikona konta Nie znaleziono konta! - Wyczyść nieudane wysyłanie Edytuj Wyczyść wszystkie powiadomienia Opróżnij kosz @@ -153,7 +152,6 @@ Czy na pewno chcesz usunąć %1$s wraz z zawartością? Czy na pewno chcesz usunąć wybrane pozycje i ich zawartość? Tylko lokalnie - Błąd podczas tworzenia dialogu konfliktu! Plik powodujący konflikt %1$s Plik lokalny Jeśli wybierzesz obie wersje, to do nazwy pliku lokalnego zostanie dodany numer. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9049bf3b6872..1de92b5d710f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -7,7 +7,6 @@ Falha ao criar conta Ícone da conta Conta não encontrada! - Apagar envios com falha Editar Apagar todas as notificações Esvaziar lixeira @@ -57,6 +56,8 @@ Não foi possível buscar os tipos de tarefas. Verifique sua conexão com a Internet. Assistente Desconhecido + Entrada + Saída Conta associada não encontrada! O acesso falhou: %1$s A conta ainda não está adicionada neste dispositivo @@ -171,7 +172,6 @@ Quer realmente excluir %1$s e seu conteúdo? Quer realmente excluir os itens selecionados e seus conteúdos? Somente local - Erro ao criar diálogo de conflito! Arquivo conflitante %1$s Arquivo local Se você selecionar as duas versões, o arquivo local terá um número anexado ao seu nome. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 93615fe7e646..0393ad0c6ef0 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -7,7 +7,6 @@ Criação de conta falhou Ícone de conta Conta não encontrada! - Limpar envios falhados Editar Limpar todas as notifcações Esvaziar a reciclagem @@ -150,7 +149,6 @@ Deseja realmente apagar %1$s e o seu conteúdo? Quer realmente apagar os itens seleccionados e os seus conteúdos? Apenas localmente - Erro ao criar a janela de conflito! Ficheiro em conflito %1$s Ficheiro local Se selecionou ambas as versões, o ficheiro local terá um número acrescentado ao seu nome. diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 57598577b2fe..a75583470fbd 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -7,7 +7,6 @@ Eroare la crearea contului Iconița contului Contul nu a fost găsit! - Elimină încărcările eșuate Editare Elimină toate notificările Golește coșul de gunoi @@ -150,7 +149,6 @@ Sigur vreți să eliminați %1$s și conținutul său? Doriți să ștergeți elementele selectate și conținutul lor? Doar local - Eroare la crearea dialogului pentru conflict! Conflict cu fișierul %1$s Fișier local Dacă selectezi ambele variante, atunci fișierul local va avea un număr adăugat la numele său. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fd87b685db0d..88ebecacc108 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -7,7 +7,6 @@ Ошибка создания учетной записи Значок учётной записи Учётная запись не найдена! - Убрать неудавшиеся загрузки Редактировать Удалить все уведомления Очистить корзину @@ -158,7 +157,6 @@ Действительно удалить «%1$s» и его содержимое? Действительно удалить выбранные объекты и их содержимое? Только локально - Не удалось создать диалоговое окно разрешения конфликта синхронизации. Конфликт версий файла «%1$s» Локальный файл Если вы выберете обе версии, локальный файл будет иметь номер, добавленный к его имени. diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 8a6f92e90331..6fc476d640b0 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -7,7 +7,6 @@ Errore in sa creatzione de su contu Icona de su contu Contu no agatadu! - Boga·nche is carrigamentos faddidos Modìfica Boga·nche totu is notìficas Bòida s\'àliga @@ -144,7 +143,6 @@ A beru boles cantzellare %1$s e is cuntenutos suos? A beru boles cantzellare is elementos seberados e is cuntenutos issoro? Locale isceti - Errore creende una bentana de cunflitu! Archìviu in cunflitu %1$s Si seletzionas ambas is versiones, s\'archìviu locale at a tènnere unu nùmeru in agiunta a su nùmene. Icona utente pro lista de cuntatos diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index e396c88bfc47..2d9d9fcf03a7 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -7,7 +7,6 @@ Vytvorenie účtu sa nepodarilo Ikona účtu Účet sa nenašiel! - Odstrániť zlyhané nahrávania Upraviť Odstrániť všetky upozornenia Vyprázdniť kôš @@ -171,7 +170,6 @@ Naozaj chcete odstrániť %1$s a jeho obsah? Naozaj chcete odstrániť vybraté položky a ich obsah? Iba lokálne - Chyba pri vytváraní konfliktného dialógového okna! Konfliktný súbor %1$s Lokálny súbor Ak vyberiete obe verzie, miestny súbor bude mať k svojmu názvu pridané číslo. diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 649b9df23bd0..5b72b578d41e 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -7,7 +7,6 @@ Ustvarjanje računa je spodletelo ikona računa Računa ni mogoče najti! - Počisti dnevnik spodletelih pošiljanj Uredi Počisti vsa obvestila Izprazni smeti @@ -153,7 +152,6 @@ Ali res želite izbrisati %1$s skupaj z vsebino? Ali zares želite izbrisati izbrane predmete in vsebino? Le krajevno - Prišlo je do napake med ustvarjanjem pogovornega okna spora! Različice %1$s v sporu. Krajevna datoteka Če izberete obe različici, bo k imenu krajevne datoteke dodana številka. diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 600a73fb3ce1..50f7c9c863e6 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -7,7 +7,6 @@ Krijimi i llogarisë dështoi Ikona e llogarisë Llogaria nuk u gjet! - Pastroni ngarkimet e dështuara Përpuno Pastro të gjithë njoftimet Dërgoje/Shpërndaje @@ -131,7 +130,6 @@ Doni vërtet të hiqet %1$s dhe përmbajtja e tij? Doni vërtet të hiqni artikujt e zgjedhur dhe përmbajtjen e tyre? Vetëm vendorja - Gabim në krijimin e dialogut për konflikte! Nëse zgjidhni të dy versionet, skedari lokal do të ketë një numër të bashkangjitur në emër Ikona e përdoruesit për listën e kontakteve Asnjë leje e dhënë, nuk u importua asgjë. diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 6343160a1f3e..d7f12e426d8b 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -8,7 +8,6 @@ Pravljenje naloga nije uspelo Ikona naloga Nalog nije nađen! - Izbriši neuspela otpremanja Izmeni Očisti sva obaveštenja Slanje/Deljenje diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 30d08f507a51..67593933060b 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -7,7 +7,6 @@ Прављење налога није успело Икона налога Налог није нађен! - Избриши неуспела отпремања Уреди Очисти сва обавештења Испразни корпу за отпатке @@ -57,6 +56,8 @@ Не могу да се преузму типови задатака, молимо вас да проверите везу са интернетом. Асистент Непознато + Унос + Излаз Придружени налог није нађен! Неуспешан приступ: %1$s Налог још није додат на овај уређај @@ -171,7 +172,6 @@ Заиста желите да обришете %1$s и сав њен садржај? Заиста желите да обришете означене ставке и њихов садржај? Само локално - Грешка при прављењу дијалога сукоба! Конфликтни фајл %1$s Локални фајл Ако изаберете обе верзије, локални фајл имаће број придодат свом називу. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 703267b6e654..453b194c8379 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -7,7 +7,6 @@ Skapande av konto misslyckades Kontoikon Kontot hittades inte! - Ta bort misslyckade uppladdningar Redigera Rensa alla aviseringar Töm papperskorgen @@ -57,6 +56,7 @@ Det går inte att hämta uppgiftstyper, kontrollera din internetanslutning. Assistent Okänd + Inmatning Associerat konto kunde inte hittas! Åtkomst misslyckades: %1$s Kontot har ännu inte lagts till på den här enheten @@ -171,7 +171,6 @@ Vill du verkligen ta bort %1$s och dess innehåll? Vill du verkligen radera de valda objekten och dess innehåll? Endast lokalt - Fel vid skapande av konfliktdialog! Konfliktande fil %1$s Lokal fil Om du väljer båda versionerna kommer den lokala filen få ett nummer tillagt i filnamnet. diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th-rTH/strings.xml index 6b2168742ee0..1e3da07892b5 100644 --- a/app/src/main/res/values-th-rTH/strings.xml +++ b/app/src/main/res/values-th-rTH/strings.xml @@ -7,7 +7,6 @@ การสร้างบัญชีล้มเหลว ไอคอนบัญชี ไม่พบบัญชี! - ล้างการอัปโหลดที่ล้มเหลว แก้ไข ล้างการแจ้งเตือน ล้างข้อมูลในถังขยะ @@ -147,7 +146,6 @@ คุณต้องการลบ %1$s และเนื้อหาที่อยู่ในนั้นจริง ๆ หรือไม่? คุณต้องการลบรายการที่เลือกและเนื้อหาที่อยู่ในนั้นจริง ๆ หรือไม่? เฉพาะต้นทางเท่านั้น - ข้อผิดพลาดในการสร้างกล่องโต้ตอบข้อขัดแย้ง! ขัดขัดแย้งไฟล์ %1$s ไฟล์ต้นทาง ถ้าคุณเลือกทั้งสองรุ่น ชื่อของไฟล์ที่อยู่ในเครื่องจะมีตัวเลขเพิ่มเข้าไป diff --git a/app/src/main/res/values-tk/strings.xml b/app/src/main/res/values-tk/strings.xml index ba8ed96063c3..962c6b34d48f 100644 --- a/app/src/main/res/values-tk/strings.xml +++ b/app/src/main/res/values-tk/strings.xml @@ -7,7 +7,6 @@ Akaunt döretmeklik şowsuz boldy Hasap nyşany Hasap tapylmady - Şowsuz ýüklemeleri arassalaň Redaktirläň ähli bildirişleri arassala Iber / Paýlaş @@ -137,7 +136,6 @@ Hakykatdan hem %1$sonuň mazmuny hem pozmak isleýärsiňizmi? Saýlanan elementleri we olaryň mazmunyny hakykatdanam pozmak isleýärsiňizmi? Diňe ýerli - Jedelli gepleşikleri döretmekdäki ýalňyşlyk! Jedelli faýl%1$s Eger siz iki wersiýasyny hem saýlasaňyz, ýerli faýlyň adyna san goşular. Aragatnaşyk sanawy üçin ulanyjy nyşany diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 43b1e0e7864a..e2c1d451f4ec 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -7,7 +7,6 @@ Hesap oluşturulamadı Hesap simgesi Hesap bulunamadı! - Tamamlanamayan yüklemeler silinsin Düzenle Tüm bildirimleri temizle Çöp kutusunu boşalt @@ -57,6 +56,8 @@ Görev türleri alınamadı. Lütfen İnternet bağlantınızı denetleyin. Yardımcı Bilinmiyor + Giriş + Çıktı İlişkili hesap bulunamadı! Erişilemedi: %1$s Aygıt üzerinde henüz bu hesap açılmamış @@ -171,7 +172,6 @@ %1$s klasörünü ve içindekileri silmek istediğinize emin misiniz? Seçilmiş ögeleri ve içindekileri silmek istediğinize emin misiniz? Yalnızca yerel - Çakışma penceresi oluşturulurken sorun çıktı! %1$s dosyası çakışıyor Yerel dosya İki sürümü de saklamayı seçerseniz, yerel dosyanın adına bir numara eklenecek. diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index b1974fff65ff..0e310d690b6d 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -7,7 +7,6 @@ Не вдалося створити обліковий запис Зображення облікового запису Обліковий запис не знайдено! - Очистити невдалі завантаження Редагувати Очистити всі сповіщення Очистити кошик @@ -171,7 +170,6 @@ Ви справді бажаєте вилучити %1$s та його вміст? Дійсно вилучити вибрані об\'єкти та їхній вміст? Лише на пристрої - Помилка у створенні діалогу щодо конфлікту! Конфліктний файл %1$s Файл на пристрої Якщо ви виберете обидві версії, то до назви локального файлу буде додано порядковий номер. diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index acf96f9d6f57..968796c73bf8 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -7,7 +7,6 @@ Tạo tài khoản không thành công Biểu tượng tài khoản Không tìm thấy tài khoản! - Dọn dẹp các tải lên bị lỗi Chỉnh sửa Xoá tất cả thông báo Dọn sạch thùng rác @@ -147,7 +146,6 @@ Bạn có thực sự muốn xóa %1$s và nội dung của nó? Bạn có thực sự muốn xóa các mục đã chọn và nội dung của chúng không? Chỉ cục bộ - Lỗi khi tạo hộp thoại xung đột! Tập tin xung đột %1$s Tệp cục bộ Nếu bạn chọn cả hai phiên bản, tệp trên máy sẽ có một số được thêm vào tên của nó. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 230e09218600..ff8fee2903eb 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -7,7 +7,6 @@ 账号创建失败 账号图标 找不到账号! - 清除失败上传任务 编辑 清除所有通知 清空垃圾箱 @@ -47,6 +46,7 @@ 任务已创建 任务已删除 未知 + 输出结果 相关账号未找到! 访问已失败: %1$s 该账号尚未添加到此设备上 @@ -161,7 +161,6 @@ 确定删除%1$s及其相关内容? 确定删除选中项及其内容? 仅本地 - 创建冲突会话时出错! 冲突文件 %1$s 本地文件 如果您选择两个版本,则本地文件的名称后面将附加一个数字。 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 612b54311747..032e3562dfc4 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -7,7 +7,6 @@ 建立賬戶失敗 賬戶圖示 沒有找到任何賬戶 - 清除失敗的上傳 編輯 清除所有通知訊息 清空回收桶 @@ -57,6 +56,8 @@ 無法擷取任務類型,請檢查您的網際網路連線。 助手 不詳 + 輸入 + 輸出 無法找到連結賬戶 存取失敗:%1$s 此賬戶尚未加入到這個裝置 @@ -171,7 +172,6 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 只有近端 - 建立抵觸訊息時發生錯誤! 檔案 %1$s 抵觸 近端檔案 若您同時選擇兩個版本,近端的檔案會在檔名後附加編號。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 84e5699237f2..5d2475f444e5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -7,7 +7,6 @@ 帳號建立失敗 帳號圖示 找不到帳號! - 清除失敗的上傳 編輯 清除所有通知訊息 清空回收桶 @@ -57,6 +56,8 @@ 無法擷取工作項目類型,請檢查您的網際網路連線。 助理 未知 + 輸入 + 輸出 找不到相關的帳號! 存取失敗:%1$s 此帳號尚未加入到這個裝置 @@ -171,7 +172,6 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 僅本機 - 建立衝突對話框時發生錯誤! 檔案 %1$s 衝突 本機檔案 若您同時選擇兩個版本,本機的檔案會在檔名後附加編號。 From b22c037ab208fec634d59b76984a93f92ad363c7 Mon Sep 17 00:00:00 2001 From: nextcloud-android-bot Date: Wed, 17 Apr 2024 19:20:21 +0000 Subject: [PATCH 077/114] =?UTF-8?q?=F0=9F=94=84=20synced=20local=20'.githu?= =?UTF-8?q?b/workflows/'=20with=20remote=20'config/workflows/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nextcloud-android-bot --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e235d5a23cc2..e2612483c116 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -53,4 +53,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b14bc5d28447..d8406c85c607 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 with: sarif_file: results.sarif From e3c05e5314e7831d6faf0ba79e66ed0a2318ca37 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:23:05 +0000 Subject: [PATCH 078/114] Update dependency androidx.compose.ui:ui-tooling-preview to v1.6.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e912466a6672..017f1c83102d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -275,7 +275,7 @@ dependencies { implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.material3:material3") - implementation("androidx.compose.ui:ui-tooling-preview:1.6.5") + implementation("androidx.compose.ui:ui-tooling-preview:1.6.6") debugImplementation 'androidx.compose.ui:ui-tooling:1.6.5' compileOnly 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' From 4128c3863372f7927bec9e939e1724117ee3a7bf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:25:59 +0000 Subject: [PATCH 079/114] Update dependency androidx.compose:compose-bom to v2024.04.01 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- app/build.gradle | 2 +- gradle/verification-metadata.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e912466a6672..a10e74f79077 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -271,7 +271,7 @@ dependencies { } // Jetpack Compose - implementation(platform("androidx.compose:compose-bom:2024.04.00")) + implementation(platform("androidx.compose:compose-bom:2024.04.01")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.material3:material3") diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9692aac00dab..981bf2476029 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -766,6 +766,11 @@ + + + + + From 99814d53fd099a06dbe60cbd610822e5b49ef428 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:27:59 +0000 Subject: [PATCH 080/114] Update dependency composeOptions to v1.5.12 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e912466a6672..2ab2f2dee8b6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -259,7 +259,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.5.11" + kotlinCompilerExtensionVersion = "1.5.12" } } From e09cd62867cebf020686ed3ef6db47bafd4b41e4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:28:05 +0000 Subject: [PATCH 081/114] Update github/codeql-action action to v3.25.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e235d5a23cc2..e2612483c116 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -53,4 +53,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b14bc5d28447..d8406c85c607 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@df5a14dc28094dc936e103b37d749c6628682b60 # v3.25.0 + uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 with: sarif_file: results.sarif From 3d491b3fcd4799fe150aa36dcbe4392063cc684d Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Thu, 18 Apr 2024 02:42:51 +0000 Subject: [PATCH 082/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ar/strings.xml | 2 ++ app/src/main/res/values-b+en+001/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-uk/strings.xml | 3 +++ app/src/main/res/values-zh-rHK/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + 6 files changed, 9 insertions(+) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index f4420e1201af..889e5db28355 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -56,6 +56,7 @@ تعذّر جلب أنواع المهام. قم رجاءً بالتحقُّق من اتصالك بالإنترنت. المُساعِد غير معروف + مُدخَلات المُخرَجَات الحساب المرتبط غير موجود! فشل الوصول لـ: %1$s @@ -171,6 +172,7 @@ هل توَدُّ حقاً حذف %1$s وما يحتويه؟ هل توَدُّ حقاً حذف العناصر المختارة وما يحتوّه؟ محلياً فقط + تعذّر إنشاء نافذة حوار لحل التعارضات ملف متضارب %1$s ملف محلي إذا قمت باختيار كلا الاصدارين, الملف المحلي سيحتوي على رقم ملحق باسم الملف. diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 34545c31d13e..5ad648a14df2 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -172,6 +172,7 @@ Do you really want to delete %1$s and its content? Do you really want to delete the selected items and their contents? Local only + Conflict resolver dialogue cannot be created Conflicting file %1$s Local file If you select both versions, the local file will have a number appended to its name. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 91c7eab694a8..5761430919e7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -172,6 +172,7 @@ Wollen Sie %1$s und deren Inhalte wirklich löschen? Möchten Sie die ausgewählten Elemente und deren inhalt wirklich löschen? Nur lokal + Konfliktlösungsdialog konnte nicht erstellt werden Konflikt-Datei %1$s Lokale Datei Falls beide Versionen gewählt werden, wird bei der lokalen Datei eine Zahl am Ende des Dateinamens hinzugefügt. diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0e310d690b6d..ad6569fdd950 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -56,6 +56,8 @@ Не вдалося отримати типи завдань. Перевірте з\'єднання з мережею. Помічник Невідомо + Введення + Виведення Пов\'язаний обліковий запис не знайдено! Доступ невдалий: %1$s Обліковий запис все ще не створено на цьому пристрої @@ -170,6 +172,7 @@ Ви справді бажаєте вилучити %1$s та його вміст? Дійсно вилучити вибрані об\'єкти та їхній вміст? Лише на пристрої + Неможливо ініціювати діалог розв\'язання конфлікту Конфліктний файл %1$s Файл на пристрої Якщо ви виберете обидві версії, то до назви локального файлу буде додано порядковий номер. diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 032e3562dfc4..58e1d0b3cc78 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -172,6 +172,7 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 只有近端 + 無法創建衝突解決程序對話框 檔案 %1$s 抵觸 近端檔案 若您同時選擇兩個版本,近端的檔案會在檔名後附加編號。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5d2475f444e5..5ff629642381 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -172,6 +172,7 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 僅本機 + 無法建立衝突解決對話方塊 檔案 %1$s 衝突 本機檔案 若您同時選擇兩個版本,本機的檔案會在檔名後附加編號。 From 865ce87571fcea617db275515d236368f81785cf Mon Sep 17 00:00:00 2001 From: rakekniven <2069590+rakekniven@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:23:23 +0200 Subject: [PATCH 083/114] fix(i18n): Improved grammar Reported at Transifex Signed-off-by: rakekniven <2069590+rakekniven@users.noreply.github.com> --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4be6938752c7..a7ebed20a682 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -997,7 +997,7 @@ Thumbnail for new file Thumbnail for existing file Invalid URL - Conflict resolver dialog cannot able to created + Conflict resolver dialog cannot be created QR code could not be read! Note icon Add another link From b7f0cab77e703612fd75b07e7a24285fdf9dd3b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 10:23:49 +0000 Subject: [PATCH 084/114] fix(deps): update dependency androidx.compose.ui:ui-tooling to v1.6.6 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index c837baa7c4ef..419d0737be6f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -276,7 +276,7 @@ dependencies { implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.material3:material3") implementation("androidx.compose.ui:ui-tooling-preview:1.6.6") - debugImplementation 'androidx.compose.ui:ui-tooling:1.6.5' + debugImplementation 'androidx.compose.ui:ui-tooling:1.6.6' compileOnly 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' // remove after entire switch to lib v2 From 09f98b8b6d64e9e49bfc6612286b362ba36b7e9c Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Thu, 18 Apr 2024 16:50:36 +0000 Subject: [PATCH 085/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-b+en+001/strings.xml | 1 - app/src/main/res/values-cs-rCZ/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es-rMX/strings.xml | 2 ++ app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - 8 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 889e5db28355..317d4f3a5bb3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -172,7 +172,6 @@ هل توَدُّ حقاً حذف %1$s وما يحتويه؟ هل توَدُّ حقاً حذف العناصر المختارة وما يحتوّه؟ محلياً فقط - تعذّر إنشاء نافذة حوار لحل التعارضات ملف متضارب %1$s ملف محلي إذا قمت باختيار كلا الاصدارين, الملف المحلي سيحتوي على رقم ملحق باسم الملف. diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 5ad648a14df2..34545c31d13e 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -172,7 +172,6 @@ Do you really want to delete %1$s and its content? Do you really want to delete the selected items and their contents? Local only - Conflict resolver dialogue cannot be created Conflicting file %1$s Local file If you select both versions, the local file will have a number appended to its name. diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 68c1ac692513..0341e0184497 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -42,6 +42,7 @@ Dokončeno Úloha úspěšně smazána Neznámé + Vstup Výstup Související účet nenalezen! Přístup se nezdařil: %1$s diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5761430919e7..91c7eab694a8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -172,7 +172,6 @@ Wollen Sie %1$s und deren Inhalte wirklich löschen? Möchten Sie die ausgewählten Elemente und deren inhalt wirklich löschen? Nur lokal - Konfliktlösungsdialog konnte nicht erstellt werden Konflikt-Datei %1$s Lokale Datei Falls beide Versionen gewählt werden, wird bei der lokalen Datei eine Zahl am Ende des Dateinamens hinzugefügt. diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 607f89aa834c..85b55c381b1c 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -56,6 +56,8 @@ No se pudieron obtener los tipos de tareas, por favor, revise su conexión a internet. Asistente Desconocido + Entrada + Salida ¡No se encontró la cuenta asociada! Acceso fallido:%1$s La cuenta aún no ha sido agregada a este dispositivo diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index ad6569fdd950..37eaac6a932a 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -172,7 +172,6 @@ Ви справді бажаєте вилучити %1$s та його вміст? Дійсно вилучити вибрані об\'єкти та їхній вміст? Лише на пристрої - Неможливо ініціювати діалог розв\'язання конфлікту Конфліктний файл %1$s Файл на пристрої Якщо ви виберете обидві версії, то до назви локального файлу буде додано порядковий номер. diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 58e1d0b3cc78..032e3562dfc4 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -172,7 +172,6 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 只有近端 - 無法創建衝突解決程序對話框 檔案 %1$s 抵觸 近端檔案 若您同時選擇兩個版本,近端的檔案會在檔名後附加編號。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5ff629642381..5d2475f444e5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -172,7 +172,6 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 僅本機 - 無法建立衝突解決對話方塊 檔案 %1$s 衝突 本機檔案 若您同時選擇兩個版本,本機的檔案會在檔名後附加編號。 From 9bc5d3ff4abaed446287552583f773375c7bd211 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 19:40:24 +0000 Subject: [PATCH 086/114] chore(deps): update actions/upload-artifact action to v4.3.2 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/screenShotTest.yml | 2 +- .github/workflows/unit-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/screenShotTest.yml b/.github/workflows/screenShotTest.yml index 72b5229a5899..3cfc292a5afa 100644 --- a/.github/workflows/screenShotTest.yml +++ b/.github/workflows/screenShotTest.yml @@ -93,7 +93,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: scripts/uploadReport.sh "${{ secrets.LOG_USERNAME }}" "${{ secrets.LOG_PASSWORD }}" ${{github.event.number}} "${{ matrix.color }}-${{ matrix.scheme }}" "Screenshot" ${{github.event.number}} - name: Archive Espresso results - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 if: ${{ always() }} with: name: Report-${{ matrix.color }}-${{ matrix.scheme }} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 0820761ac1c3..ff07b97b3925 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -49,7 +49,7 @@ jobs: fail_ci_if_error: true - name: Upload jacoco artifacts if: ${{ failure() }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 with: name: test-results path: app/build/reports/tests/testGplayDebugUnitTest/ From a70fadeb63dceadfe98dbd55f26aef83ac018cc8 Mon Sep 17 00:00:00 2001 From: nextcloud-android-bot Date: Fri, 19 Apr 2024 02:22:53 +0000 Subject: [PATCH 087/114] =?UTF-8?q?=F0=9F=94=84=20synced=20local=20'.githu?= =?UTF-8?q?b/workflows/'=20with=20remote=20'config/workflows/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nextcloud-android-bot --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index e6f8faa74cf3..9c6e46f63c7b 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -26,4 +26,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: gradle/wrapper-validation-action@460a3ca55fc5d559238a0efc7fa9f7465df8585d # v3.3.0 + - uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af # v3.3.1 From 9604995dc7e5a21ac26d3942d99bdbcb51929a79 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 19 Apr 2024 02:44:25 +0000 Subject: [PATCH 088/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ar/strings.xml | 1 + app/src/main/res/values-b+en+001/strings.xml | 1 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-zh-rHK/strings.xml | 63 ++++++++++---------- app/src/main/res/values-zh-rTW/strings.xml | 1 + 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 317d4f3a5bb3..bc83e430237b 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -172,6 +172,7 @@ هل توَدُّ حقاً حذف %1$s وما يحتويه؟ هل توَدُّ حقاً حذف العناصر المختارة وما يحتوّه؟ محلياً فقط + تعذّر إنشاء نافذة حوار حل التعارضات ملف متضارب %1$s ملف محلي إذا قمت باختيار كلا الاصدارين, الملف المحلي سيحتوي على رقم ملحق باسم الملف. diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 34545c31d13e..27c89263b58d 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -172,6 +172,7 @@ Do you really want to delete %1$s and its content? Do you really want to delete the selected items and their contents? Local only + Conflict resolver dialog cannot be created Conflicting file %1$s Local file If you select both versions, the local file will have a number appended to its name. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 91c7eab694a8..5761430919e7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -172,6 +172,7 @@ Wollen Sie %1$s und deren Inhalte wirklich löschen? Möchten Sie die ausgewählten Elemente und deren inhalt wirklich löschen? Nur lokal + Konfliktlösungsdialog konnte nicht erstellt werden Konflikt-Datei %1$s Lokale Datei Falls beide Versionen gewählt werden, wird bei der lokalen Datei eine Zahl am Ende des Dateinamens hinzugefügt. diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 032e3562dfc4..da4ab7bc480a 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -4,9 +4,9 @@ 關於 版本 %1$s 版本 %1$s,組建 #%2$s - 建立賬戶失敗 - 賬戶圖示 - 沒有找到任何賬戶 + 建立帳戶失敗 + 帳戶圖示 + 沒有找到任何帳戶 編輯 清除所有通知訊息 清空回收桶 @@ -58,11 +58,11 @@ 不詳 輸入 輸出 - 無法找到連結賬戶 + 無法找到連結帳戶 存取失敗:%1$s - 此賬戶尚未加入到這個裝置 - 此裝置上已經存在同樣伺服器與用戶賬戶 - 輸入的用戶與此賬戶的用戶不一致 + 此帳戶尚未加入到這個裝置 + 此裝置上已經存在同樣伺服器與用戶帳戶 + 輸入的用戶與此帳戶的用戶不一致 無法辨識的伺服器版本 連線已建立 您的伺服器並未回傳正確的用戶名稱,請您聯絡相關管理人員。 @@ -86,7 +86,7 @@ 發生未知的HTTP錯誤! 發生了不詳的錯誤! 無法找到主機 - %1$s 不支援多個賬戶 + %1$s 不支援多個帳戶 無法建立連線 以唯讀模式保留在原本的資料夾 僅在未計量的Wi-Fi上傳 @@ -127,7 +127,7 @@ 返回 取消 取消同步 - 選擇賬戶 + 選擇帳戶 確認 複製 刪除 @@ -145,8 +145,8 @@ 傳送 分享 略過 - 切換賬戶 - 切換到賬戶 + 切換帳戶 + 切換到帳戶 測試開發版本 這包含所有最新功能,預期執行上仍可能會有錯誤,若發現錯誤請舉報給我們。 @@ -172,6 +172,7 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 只有近端 + 無法創建衝突解決程序對話框 檔案 %1$s 抵觸 近端檔案 若您同時選擇兩個版本,近端的檔案會在檔名後附加編號。 @@ -209,7 +210,7 @@ 每日備份 要備份的數據 不正確的認證方式 - 刪除賬戶 + 刪除帳戶 刪除條目 刪除連結 取消全選 @@ -309,13 +310,13 @@ 顯示檔案操作時出錯 更改檔案上鎖狀態時出錯 舉報 - 想舉報問題?(需要GitHub賬戶) + 想舉報問題?(需要GitHub帳戶) 檢索檔案時發生錯誤 取得範本時發生錯誤 顯示加密設定對話方塊時發生錯誤! 無法啟動相機 文件掃描開始時出錯 - 賬戶 + 帳戶 時段運行在48小時內 創建於 工作名稱 @@ -389,8 +390,8 @@ 完成 取代 準備遷移… - 回復賬戶設置中… - 正在儲存賬戶設置… + 回復帳戶設置中… + 正在儲存帳戶設置… 您仍然想要變更資料儲存資料夾為 %1$s 嗎?\n\n注意:所有資料都必須再次下載。 來源資料夾無法讀取 更新索引中… @@ -539,7 +540,7 @@ 沒有可用於處理郵件地址的應用程式 沒有項目 沒有應用程式可以處理地圖 - 只可使用一個賬戶 + 只可使用一個帳戶 沒有應用程式可以開啟 PDF 沒有可用於發送所選檔案的應用程式 請選取至少一個要分享的權限。 @@ -601,10 +602,10 @@ 覆寫遠端的版本 重新命名新的版本 當檔案已經存在時我該怎麼做? - 新增賬戶 + 新增帳戶 同步日曆與通訊錄 尚未安裝 F-Droid 或 Google Play - 為目前用戶賬戶設定 DAVx5 協定(以前稱為 DAVdroid)(版本 v1.3.0 以上) + 為目前用戶帳戶設定 DAVx5 協定(以前稱為 DAVdroid)(版本 v1.3.0 以上) 日曆與通訊錄同步設定 關於 詳細資料 @@ -638,7 +639,7 @@ 使用以下工具保護 app 裝置身分驗證方式 通行碼 - 管理賬戶 + 管理帳戶 向朋友推薦 移除近端加密 設置端對端加密 @@ -661,7 +662,7 @@ 私隱政策 新名稱 由於依賴專有的Google Play服務,推送通知已停用。 - 由於登入已過期,因此沒有推送通知。請考慮重新添加您的賬戶。 + 由於登入已過期,因此沒有推送通知。請考慮重新添加您的帳戶。 推送通知目前無法使用。 QR 碼無法讀取! 在您的裝置上試用 %1$s! @@ -674,17 +675,17 @@ 您可以在此客戶端上本地刪除端到端加密 您可以在此客戶端上本地刪除端到端加密。加密檔案將保留在伺服器上,但不會再同步到此電腦。 刪除失敗 - 移除近端賬戶 - 從裝置中刪除賬戶並刪除所有近端檔案 + 移除近端帳戶 + 從裝置中刪除帳戶並刪除所有近端檔案 移除通知失敗 移除 已刪除 輸入新名稱 無法重新命名近端複本,請試用不同名稱 不可重新命名,名稱已存在 - 請求賬戶刪除 + 請求帳戶刪除 請求刪除 - 請求服務提供者永久刪除賬戶 + 請求服務提供者永久刪除帳戶 不允許重新分享 不允許重新分享 沒有可用調整過的圖像,下載完整圖像? @@ -702,7 +703,7 @@ 全在您一指之間 活動、分享… 可快速存取所有資源 - 您所有的賬戶 + 您所有的帳戶 在一個地方 自動上傳 您的照片與視像 @@ -773,7 +774,7 @@ 顯示照片 顯示影片 使用第三方登入 - 允許 %1$s 存取您的 Nextcloud 賬戶 %2$s? + 允許 %1$s 存取您的 Nextcloud 帳戶 %2$s? 排序方式 隱藏 細節 @@ -812,7 +813,7 @@ 完整存取權限 僅媒體唯讀 圖片 - 可自架且始終讓您掌控一切的生產力平台。\n功能:\n* 簡潔、現代的用戶界面,適合您伺服器的佈景主題\n* 上傳檔案到您的 Nextcloud 伺服器\n* 與其他人分享檔案\n* 讓您最愛的檔案與資料夾同步\n* 搜尋您伺服器上所有的資料夾\n* 以通知訊息保持更新\n* 多賬戶支援\n* 使用指紋或 PIN 碼安全存取您的資料\n* 與 DAVx5 整合(先前被稱為 DAVdroid),可輕易設定行事曆與聯絡人同步\n\n請至 https://github.com/nextcloud/android/issues 舉報所有問題,並於 https://help.nextcloud.com/c/clients/android 討論此應用程式\n\n您是 Nextcloud 新手嗎?Nextcloud 是一個私人的檔案同步、共享與通訊的伺服器。它是自由軟體,您可以自行架設,或是付費請專業公司協助您建置。如此,您便可完全掌控您的照片、行事曆與聯絡人資料、您的文件與其他任何東西。\n\n請造訪 https://nextcloud.com 以取得更多資訊 + 可自架且始終讓您掌控一切的生產力平台。\n功能:\n* 簡潔、現代的用戶界面,適合您伺服器的佈景主題\n* 上傳檔案到您的 Nextcloud 伺服器\n* 與其他人分享檔案\n* 讓您最愛的檔案與資料夾同步\n* 搜尋您伺服器上所有的資料夾\n* 以通知訊息保持更新\n* 多帳戶支援\n* 使用指紋或 PIN 碼安全存取您的資料\n* 與 DAVx5 整合(先前被稱為 DAVdroid),可輕易設定行事曆與聯絡人同步\n\n請至 https://github.com/nextcloud/android/issues 舉報所有問題,並於 https://help.nextcloud.com/c/clients/android 討論此應用程式\n\n您是 Nextcloud 新手嗎?Nextcloud 是一個私人的檔案同步、共享與通訊的伺服器。它是自由軟體,您可以自行架設,或是付費請專業公司協助您建置。如此,您便可完全掌控您的照片、行事曆與聯絡人資料、您的文件與其他任何東西。\n\n請造訪 https://nextcloud.com 以取得更多資訊 可自架且始終讓您掌控一切的生產力平台。\n這是官方的開發版本,每天都會提供未經測試的任何新功能的範例,可能造成不穩定或資料遺失。此應用程式適合願意測試且舉報遇到的問題的用戶。不要將其用於您的生產力工作!\n\nF-Droid 同時提供了官方的開發版本與一般版本,可同時安裝。 讓你能完全掌控、自建且具生產力的平台 讓你能完全掌控、自建且具生產力的平台(開發者預覽版) @@ -838,7 +839,7 @@ 同步失敗,需重新登入。 檔案已同步 無法完成資料夾 %1$s 的同步作業 - 於1.3.16版本中,此裝置已上傳的檔案會複製到近端%1$s資料夾,以防止多重賬戶同步單一檔案時造成遺失。透過此應用程式更早的版本上傳的檔案則複製到%2$s資料夾。但是在同步時出現錯誤會阻礙此操作完成,你可以選擇無視此檔案並移除%3$s的連結,或者移動此檔案到%1$s資料夾並保留%4$s的連結,下面列出%5$s中近端與遠端檔案之間的連結。 + 於1.3.16版本中,此裝置已上傳的檔案會複製到近端%1$s資料夾,以防止多重帳戶同步單一檔案時造成遺失。透過此應用程式更早的版本上傳的檔案則複製到%2$s資料夾。但是在同步時出現錯誤會阻礙此操作完成,你可以選擇無視此檔案並移除%3$s的連結,或者移動此檔案到%1$s資料夾並保留%4$s的連結,下面列出%5$s中近端與遠端檔案之間的連結。 有些近端端的檔案已遺失 取得檔案最近的版本 選擇同步項目 @@ -948,8 +949,8 @@ %1$s 已上傳 退出 設定 - 無 %1$s 賬戶,請先建立賬戶。 - 找不到賬戶 + 無 %1$s 帳戶,請先建立帳戶。 + 找不到帳戶 目前 失敗/等待重啟 已上傳 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 5d2475f444e5..5ff629642381 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -172,6 +172,7 @@ 你真的想要刪除 %1$s 與裡面的檔案? 您真的想要刪除所選項目和裡面的內容嗎? 僅本機 + 無法建立衝突解決對話方塊 檔案 %1$s 衝突 本機檔案 若您同時選擇兩個版本,本機的檔案會在檔名後附加編號。 From 5ca90493e4af6dd80c588b0d32782ceacb35b460 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sat, 20 Apr 2024 02:49:35 +0000 Subject: [PATCH 089/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-es-rMX/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 15 ++++++++------- app/src/main/res/values-ru/strings.xml | 21 +++++++++++++++++++++ app/src/main/res/values-sr/strings.xml | 1 + 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 85b55c381b1c..491cc36e7082 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -172,6 +172,7 @@ ¿Realmente quieres eliminar %1$s y sus contenidos? ¿Reamente deseas eliminar los elementos seleccionados y sus contenidos? Sólo local + El diálogo de resolución de conflictos no puede ser creado Archivo conflictivo %1$s Archivo local Si seleccionas ambas versiones, el archivo local tendrá un número al final del nombre. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1370acfc6ae6..10a08b91346f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -13,7 +13,7 @@ Envoyer / Partager Affichage mosaïque Affichage liste - Restaurer les contacts et l’agenda + Restaurer les contacts et l\'agenda Nouveau dossier Déplacer ou copier Ouvrir avec @@ -412,7 +412,7 @@ Nom du fichier Sécurisez et contrôlez vos données Collaboration et échange de fichiers sécurisés - Messagerie web, agenda, contacts faciles à utiliser + Webmail, agenda, contacts faciles à utiliser Partage d’écran, réunions en ligne et conférences en ligne Le dossier existe déjà Créer @@ -460,7 +460,7 @@ %s s dans le dossier %1$s Téléverser aussi les fichiers existants - Téléverser uniquement si le chargeur est branché + Téléverser uniquement lors de la recharge /InstantUpload URL invalide Invisible @@ -688,7 +688,7 @@ Le repartage est interdit Aucune image réduite disponible. Télécharger l\'image originale ? Restaurer le fichier - Restaurer la sauvegarde + Restaurer une sauvegarde Restaurer le fichier supprimé Restaurer la sélection Téléchargement en cours… @@ -768,6 +768,7 @@ partagé par lien Partagé avec vous par %1$s L\'ajout du partage a échoué + L\'ajout du partage a échoué. Ce fichier ou dossier a déjà été partagé avec cette personne ou ce groupe. Afficher les photos Afficher les vidéos Se connecter avec un fournisseur @@ -885,7 +886,7 @@ Effacer les téléversements annulés Poursuivre les téléversements annulés Effacer les téléversements échoués - Relancer les envois en erreur + Réessayer les téléversements qui ont échoué Certains fichiers n’existent pas et ne peuvent pas être relancés. Suspendre tous les téléversements Poursuivre tous les téléversements @@ -927,11 +928,11 @@ Fichier non trouvé. Êtes-vous sûr que ce fichier existe ou qu\'un conflit précédent n\'a pas été résolu ? Impossible de retrouver le fichier sur le serveur. Un autre utilisateur l\'a peut-être supprimé Nom du dossier - Réessayer de téléverser les fichiers locaux ayant échoués + Réessayer de téléverser les fichiers locaux qui ont échoué Sélectionnez le dossier de téléversement Impossible d\'envoyer %1$s Le téléversement a échoué, reconnectez-vous - Conflit de fichier lors de l\'envoi + Conflit de téléversement de fichiers Sélectionnez la version de %1$s à conserver Échec du téléversement Option de téléversement : diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 88ebecacc108..e0d0b13d6bc7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -38,11 +38,26 @@ Искать в %s Все Наберите какой-то текст + Вы уверены, что хотите удалить эту задачу? + Удалить задачу Не удалось + Список задач загружается, пожалуйста подождите + Нет доступных задач. Выберите тип задачи, чтобы создать новую задачу. + Нет доступной задачи для типа задачи %s, вы можете создать новую задачу в правом нижнем углу. + Выполянется Запланированное Выполнено + Произошла ошибка при создании задачи + Задача успешно создана + Произошла ошибка во время удаления задачи Задача удалена + Не удается получить список задач, проверьте ваше подключение к Интернету. + Удалить задачу + Не удается получить список задач, проверьте ваше подключение к Интернету. + Помощник Неизвестно + Ввод + Вывод Связанный аккаунт не найден! Доступ запрещен: %1$s Учётная запись ещё не создана на этом устройстве @@ -157,6 +172,7 @@ Действительно удалить «%1$s» и его содержимое? Действительно удалить выбранные объекты и их содержимое? Только локально + Не удается создать диалоговое окно разрешения конфликтов Конфликт версий файла «%1$s» Локальный файл Если вы выберете обе версии, локальный файл будет иметь номер, добавленный к его имени. @@ -240,6 +256,7 @@ Фоновое изображение заголовка События Все файлы + Помощник Избранное Медиа Групповые папки @@ -258,6 +275,7 @@ Автоматическая передача Сквозное шифрование не настроено Невозможно без подключения к интернету + Помощник Больше Заметки Конференции @@ -729,6 +747,7 @@ Поделиться ссылкой (%1$s) Установить срок действия Задать пароль + Перенаправление запрещено во время безопасного удаления файлов Защищено паролем Разрешено редактировать Принимать файлы @@ -752,6 +771,7 @@ поступ по ссылке С вами поделился %1$s Не удалось открыть общий доступ + Не удалось добавить общий ресурс. Этому пользователю или группе уже предоставлен общий доступ к этому файлу или папке. Показать фотографии Показать видео Подключиться через поставщика услуги @@ -794,6 +814,7 @@ Полный доступ Носитель только для чтения Изображения + Собственная продуктивная платформа, которая держит вас под контролем.\n\nFeatures:\n* Простой, современный интерфейс, соответствующий тематике вашего сервера\n* Загрузите файлы на свой сервер Nextcloud\n* Делитесь ими с другими\n* Синхронизируйте ваши любимые файлы и папки\n* Поиск во всех папках на вашем сервере\n* Автоматическая отправка фотографий и видео с вашего устройства\n* Будьте в курсе с уведомлениями\n* Поддержка нескольких учетных записей\n* Безопасный доступ к вашим данным с помощью отпечатка пальцев или PIN-кода\n* Интеграция с DAVx5 (ранее известный как DAVdroid) для легкой настройки синхронизации календаря и контактов\n\nПожалуйста, сообщите обо всех проблемах на https://github.com/nextcloud/android/issues и обсудите это приложение на https://help.nextcloud.com/c/clients/android\n\nНовичок в Nextcloud? Nextcloud - это частный сервер синхронизации и обмена файлами и коммуникационный сервер. Это свободное программное обеспечение, и вы можете разместить его самостоятельно или заплатить компании, чтобы сделать это за вас. Таким образом, вы управляете своими фотографиями, календарем и контактными данными, документами и всем остальным.\n\nПроверьте Nextcloud по адресу https://nextcloud.com Платформа, размещаемая на собственных ресурсах и позволяющая самостоятельно управлять данными.\nЭто разрабатываемая версия официального приложения Nextcloud, содержащая новые возможности, тестирование которых не ещё завершено. Разрабатываемая версия может быть нестабильна и её использование может привести к потере данных. Это приложение предназначено для пользователей, которые хотят познакомиться с новыми возможности и сообщать об обнаруженных ошибках. Не используйте его для работы!\n\nРазрабатываемая версия может быть установлена совместно с официальным приложением Nextcloud, которое также доступно в F-Droid. Платформа, размещаемая на собственных ресурсах и позволяющая самостоятельно управлять данными Платформа, размещаемая на собственных ресурсах и позволяющая самостоятельно управлять данными (разрабатываемая версия) diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 67593933060b..71a19cc8f3b5 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -172,6 +172,7 @@ Заиста желите да обришете %1$s и сав њен садржај? Заиста желите да обришете означене ставке и њихов садржај? Само локално + Нем оже да се креира дијалог за разрешавање конфилкта Конфликтни фајл %1$s Локални фајл Ако изаберете обе верзије, локални фајл имаће број придодат свом називу. From e1499019d17281ecd79bc995a0de38dc1e124e33 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 12:20:26 +0000 Subject: [PATCH 090/114] chore(deps): update gradle/gradle-build-action action to v3.3.1 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index ff07b97b3925..87ef51f729c9 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -33,7 +33,7 @@ jobs: if: ${{ always() }} run: scripts/deleteOldComments.sh "test" "Unit" ${{github.event.number}} - name: Run unit tests with coverage - uses: gradle/gradle-build-action@8baac4c8ef753599f92eeb509c246d09d6250fa6 # v3.3.0 + uses: gradle/gradle-build-action@e2097ccd7e8ed48671dc068ac4efa86d25745b39 # v3.3.1 with: arguments: jacocoTestGplayDebugUnitTest - name: Upload failing results From a6d7903ac7222de4015521900975fd40080b8f2a Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sun, 21 Apr 2024 02:45:52 +0000 Subject: [PATCH 091/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-sv/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 453b194c8379..ff83cad00522 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -171,6 +171,7 @@ Vill du verkligen ta bort %1$s och dess innehåll? Vill du verkligen radera de valda objekten och dess innehåll? Endast lokalt + Dialogrutan för konfliktlösning kan inte skapas Konfliktande fil %1$s Lokal fil Om du väljer båda versionerna kommer den lokala filen få ett nummer tillagt i filnamnet. From 1768966f4401fafc4916c07ae8af3b1caa2cef0f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:30:53 +0000 Subject: [PATCH 092/114] chore(deps): update actions/checkout action to v4.1.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/analysis.yml | 2 +- .github/workflows/assembleFlavors.yml | 2 +- .github/workflows/check.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/command-rebase.yml | 2 +- .github/workflows/detectWrongSettings.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/qa.yml | 2 +- .github/workflows/reuse.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/screenShotTest.yml | 2 +- .github/workflows/unit-tests.yml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 1d4ad457af38..da4708f09809 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -44,7 +44,7 @@ jobs: echo "repo=${{ github.event.pull_request.head.repo.full_name }}" } >> "$GITHUB_OUTPUT" fi - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: repository: ${{ steps.get-vars.outputs.repo }} ref: ${{ steps.get-vars.outputs.branch }} diff --git a/.github/workflows/assembleFlavors.yml b/.github/workflows/assembleFlavors.yml index 5be9e6321376..c1019c68a0a9 100644 --- a/.github/workflows/assembleFlavors.yml +++ b/.github/workflows/assembleFlavors.yml @@ -22,7 +22,7 @@ jobs: matrix: flavor: [ Generic, Gplay, Huawei ] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: set up JDK 17 uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3e0aa24c817a..0bd50da17f3e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -22,7 +22,7 @@ jobs: matrix: task: [ detekt, spotlessKotlinCheck ] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up JDK 17 uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e2612483c116..d9baebc93cc1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,7 +33,7 @@ jobs: language: [ 'java' ] steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set Swap Space uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0 with: diff --git a/.github/workflows/command-rebase.yml b/.github/workflows/command-rebase.yml index f448628256f6..80819d98d0f2 100644 --- a/.github/workflows/command-rebase.yml +++ b/.github/workflows/command-rebase.yml @@ -34,7 +34,7 @@ jobs: reaction-type: "+1" - name: Checkout the latest code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 0 token: ${{ secrets.COMMAND_BOT_PAT }} diff --git a/.github/workflows/detectWrongSettings.yml b/.github/workflows/detectWrongSettings.yml index fa3a2c74542a..e370c5bde800 100644 --- a/.github/workflows/detectWrongSettings.yml +++ b/.github/workflows/detectWrongSettings.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up JDK 17 uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 9c6e46f63c7b..0d0251be187d 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -25,5 +25,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af # v3.3.1 diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index f2503941f5da..c033c5e8902e 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -23,7 +23,7 @@ jobs: - name: Check if secrets are available run: echo "::set-output name=ok::${{ secrets.KS_PASS != '' }}" id: check-secrets - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 if: ${{ steps.check-secrets.outputs.ok == 'true' }} - name: set up JDK 17 uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index ec41e61ef011..0d92e5efe1ae 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -12,6 +12,6 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: REUSE Compliance Check uses: fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 # v3.0.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index d8406c85c607..c89426090214 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: persist-credentials: false diff --git a/.github/workflows/screenShotTest.yml b/.github/workflows/screenShotTest.yml index 3cfc292a5afa..70a6ef214144 100644 --- a/.github/workflows/screenShotTest.yml +++ b/.github/workflows/screenShotTest.yml @@ -25,7 +25,7 @@ jobs: color: [ blue ] api-level: [ 27 ] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Gradle cache uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 87ef51f729c9..8d3f504fd8e2 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -21,7 +21,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up JDK 17 uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: From fe5c57f86ba168bdb85bbe94bc55662b899d8f01 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:31:00 +0000 Subject: [PATCH 093/114] chore(deps): update actions/upload-artifact action to v4.3.3 Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/screenShotTest.yml | 2 +- .github/workflows/unit-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/screenShotTest.yml b/.github/workflows/screenShotTest.yml index 3cfc292a5afa..48dc3fb89ede 100644 --- a/.github/workflows/screenShotTest.yml +++ b/.github/workflows/screenShotTest.yml @@ -93,7 +93,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: scripts/uploadReport.sh "${{ secrets.LOG_USERNAME }}" "${{ secrets.LOG_PASSWORD }}" ${{github.event.number}} "${{ matrix.color }}-${{ matrix.scheme }}" "Screenshot" ${{github.event.number}} - name: Archive Espresso results - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 if: ${{ always() }} with: name: Report-${{ matrix.color }}-${{ matrix.scheme }} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 87ef51f729c9..12e100a9fa16 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -49,7 +49,7 @@ jobs: fail_ci_if_error: true - name: Upload jacoco artifacts if: ${{ failure() }} - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: test-results path: app/build/reports/tests/testGplayDebugUnitTest/ From e1b33afba3f32bbac51426f1f48c6f937f7eb8dc Mon Sep 17 00:00:00 2001 From: nextcloud-android-bot Date: Tue, 23 Apr 2024 02:23:31 +0000 Subject: [PATCH 094/114] =?UTF-8?q?=F0=9F=94=84=20synced=20local=20'.githu?= =?UTF-8?q?b/workflows/'=20with=20remote=20'config/workflows/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nextcloud-android-bot --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d9baebc93cc1..850dc0ca0ab3 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/init@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -53,4 +53,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/analyze@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index c89426090214..4074e5b0c3d7 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/upload-sarif@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 with: sarif_file: results.sarif From 0e00799071c971c92e1b609271bff4669b01676a Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Tue, 23 Apr 2024 02:44:39 +0000 Subject: [PATCH 095/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-sr-rSP/strings.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index d7f12e426d8b..e8db00c4d220 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -65,6 +65,7 @@ Isključi proveru uštede baterije Sakrij fasciklu Avatar + Odsutan Zatvori Isključi Vaš uređaj možda ima uključenu optimizaciju baterije. Automatsko otpremanje radi samo ako isključite ovu aplikaciju iz optimizacije baterije. @@ -75,6 +76,7 @@ Odaberite lokalnu fasciklu… Odaberite udaljenu fasciklu… Greška pri čišćenju obaveštenja. + Obriši statusnu poruku Tekst prekopiran sa %1$s Nema teksta za kopiranje u ostavu Veza iskopirana @@ -154,7 +156,9 @@ Isključi Odbaci Skloni obaveštenje + Ne uznemiravaj Gotovo + Ne briši Ne mogu da napravim lokalni fajl Preuzmite najnoviju razvojnu verziju Ne mogu da preuzmem %1$s @@ -294,6 +298,7 @@ Udaljeni: %1$s Svi fajlovi su premešteni Prosledi + 4 sata Ime Beleška Lozinka @@ -301,6 +306,7 @@ Hostujte sopstveni server Otpremaj samo na punjenju /InstantUpload + Nevidljiv Veza Izlistani raspored Nema fajlova u ovoj fascikli. @@ -367,6 +373,8 @@ Molimo proverite kasnije. Nema internet konekcije 1 sat + Na mreži + Mrežni status Server je izašao iz garancije, molimo ažurirajte ga! još menija Unesite kod za zaključavanje @@ -471,6 +479,8 @@ Ikona dugma za slanje Postavi kao Postavi sliku kao + Postavi status + Postavi statusnu poruku Podeli Deljenje Ističe na %1$s @@ -529,6 +539,7 @@ – Sertifikat servera nije od poverenja - Datumi važenja sertifikata su u budućnosti – Adresa se ne poklapa sa imenom domaćina u sertifikatu + Poruka stanja Kamera Odaberite lokaciju skladišta Podrazumevano @@ -671,6 +682,7 @@ Slika šta je novo Preskoči Novo u %1$s + Koji je vaš status? Skidam fajlove… Ne mogu da sinhronizujem %1$d fajl (konflikata: %2$d) From 5a5dd65478fd2ca3a535cafb1730927b47776bd8 Mon Sep 17 00:00:00 2001 From: Tobias Kaminsky Date: Tue, 23 Apr 2024 11:25:17 +0200 Subject: [PATCH 096/114] Update library Signed-off-by: Tobias Kaminsky --- build.gradle | 2 +- gradle/verification-metadata.xml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c4a9144bb143..bac1a6c1368a 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ */ buildscript { ext { - androidLibraryVersion ="0c886d61f6" + androidLibraryVersion ="5fbc7d3a9bc9fd123ce9593cc500bb6415e797c6" androidPluginVersion = '8.3.2' androidxMediaVersion = '1.3.1' androidxTestVersion = "1.5.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 981bf2476029..cb11a2ec946c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -5172,6 +5172,14 @@ + + + + + + + + From 78737d107851c451fc52478c0f1dd4ecce767199 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 23 Apr 2024 11:31:39 +0200 Subject: [PATCH 097/114] make script working Signed-off-by: tobiasKaminsky --- scripts/updateLibraryHash.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/updateLibraryHash.sh b/scripts/updateLibraryHash.sh index 34d3e5536988..4099efc09aa4 100755 --- a/scripts/updateLibraryHash.sh +++ b/scripts/updateLibraryHash.sh @@ -21,5 +21,7 @@ sed -i s"#androidLibraryVersion\ =.*#androidLibraryVersion =\"$latestCommit\"#" git add build.gradle git add gradle/verification-metadata.xml -git commit -s -m "Update library" -gh pr create --head "$(git branch --show-current)" --title "Update library $(date +%F)" --body "Update library to latest commit" +git commit -s -m "Update library to $(date +%F)" + +git push -u origin HEAD +gh pr create --fill From 2ff5006273f33fa0ab788dcfb5daa7e3891becc9 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 23 Apr 2024 11:39:36 +0200 Subject: [PATCH 098/114] fix packaging option Signed-off-by: tobiasKaminsky --- app/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle b/app/build.gradle index 419d0737be6f..90b7c0167fd8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -195,6 +195,7 @@ android { packagingOptions { resources { excludes += 'META-INF/LICENSE*' + excludes += 'META-INF/versions/9/OSGI-INF/MANIFEST*' pickFirst 'MANIFEST.MF' // workaround for duplicated manifest on some dependencies } } From 0907ec289060ac28091f7f2eb2fe8780538eea87 Mon Sep 17 00:00:00 2001 From: Marco Ambrosini Date: Tue, 23 Apr 2024 09:31:23 +0200 Subject: [PATCH 099/114] Update pdf icon Signed-off-by: Marco Ambrosini --- app/src/main/res/drawable/file_pdf.xml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/app/src/main/res/drawable/file_pdf.xml b/app/src/main/res/drawable/file_pdf.xml index 5dad2be84e59..bf9e44922246 100644 --- a/app/src/main/res/drawable/file_pdf.xml +++ b/app/src/main/res/drawable/file_pdf.xml @@ -1,16 +1,5 @@ - - - + + + + From e4b10f2f080c8a14826772cb379999c91886962c Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Tue, 23 Apr 2024 15:08:35 +0200 Subject: [PATCH 100/114] re-add SPDX header, reformat vector Signed-off-by: Andy Scherzinger --- app/src/main/res/drawable/file_pdf.xml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/drawable/file_pdf.xml b/app/src/main/res/drawable/file_pdf.xml index bf9e44922246..8a39afb69257 100644 --- a/app/src/main/res/drawable/file_pdf.xml +++ b/app/src/main/res/drawable/file_pdf.xml @@ -1,5 +1,17 @@ - - - - + + + + + From dc5fd225f9f0faa77d01cc3867a3a4c69cab1381 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Tue, 23 Apr 2024 15:09:08 +0200 Subject: [PATCH 101/114] Update screenshot Signed-off-by: Andy Scherzinger --- ...ity.UploadFilesActivityIT_noneSelected.png | Bin 13737 -> 14375 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/screenshots/gplay/debug/com.owncloud.android.ui.activity.UploadFilesActivityIT_noneSelected.png b/app/screenshots/gplay/debug/com.owncloud.android.ui.activity.UploadFilesActivityIT_noneSelected.png index c0148e4f9524bf0087ede8d65132b39b7890a8f6..fe2bf2c552035538414f4d05826bd0cb67a9b85f 100644 GIT binary patch literal 14375 zcmeHudpy&9|NkNh$yJdnLT8sWDn*gQm2|iYl_FzP$@ws14r8Q}TO~RmggKPs<~)o| z6mrUh4KquUF>{__#_zqZ>%P9%bzk@W_}-8E@%`ubc-(tD{LyEhK8N?=^*p^6dC}~Q zw4{P01OkyhclOj}2xQG11R|ooejPZn&C-nnf#^(}JN5IGfIbdG!s~@o3Uiu~`K;M; zBD47T{+w~gyxShGK9J%4;{hk$z1Y(J*yE){eP2pZt@4KXAAeYH|96$Q_x1cCg(f z+6C3>q8L9~H8mfPd#187)}5!(Y8S*g%4gTCxRIqHcL`RBYFz#Kmo0(l<0@iY=G9(H1Nr5QVR;30m4W->+9Z;(YPmLqfL!41>-4iV55| zXt*G3!c~%8|Z^J|v3%=hZ87!8}ySGjlpq3Y= z*P=1{0aI@`DxYw!@}DFq>UiFdGYp)0uP=|G;o+9x;}&@CTqLKzvXd;Br^EQVfisyl zt6%CLr8#tWcl(X^9IC?b2^>Zh?aB7zU*-oppED#SCEZt71QS2c*BV7zmhWIhkP8bb z-DgzS4o)uesXokisoUjq$dEf*c&si{HZme$tNz31b4z+&=vduL5r zOp0MB*)-LFL0qOX>JZn~4QEZebV%cZ^9voEN`H&b z`t&W2?%w@Q>`k^<{`IbePcb`gQ(wH6YS+RYzu4eiATic9mW4(m3J*{puo-$ z3~)-2IrLk8em-Ts@1x<95T2+$jB$5jfW(Fg48no#UsAs|m_1xsS&5p@n3$LvcJ)X-=AHhr zqJqe7e7tQ4k*AKCAMZ`$-DRK7v#H296HT;S`P%dx9$njC>BG2Ujr;*TW+tRZ}OtKHqWU?*C9=SEIaN;oU$vGIjXt*REa!J^Q@= z*}>enkbEPWpXAWlFlC(Q&oDbxg_VURf(QL%7#`Iwk&LwDdnnF<~s|k_nf1 zL4_?~a)K2^t<+EG>odvnCV85m;3A8B178veyT!=+9_oiISA3jt zW?NmoT8{}9D;fL2oN@QaagFLH>F2+dPV#w^Ra>5Yjy$!CD+V^R^DfDSOBttoXNFrm zTH>I1v4WiCu*gSlj1Qi>{Uz48SpSau%fIHljQFGd9Kek zvyydDw+*iz*3!a(7o+A`X{xKM5812%aG>S%vFC4_cDqxsKTGfLv*bH-!|=~|!wL6S zKR+e*1B7y}S!_e*Bbnsj-D@Dy&(6N&JJj8m@Yqd>aFWyh1=|vD7vjR9mzO6dDv)C# zcPbXs`nS`|D~zm^6x1nMrb&*Pq`7DMfiw4!dxgtQB5VL>qoWRmqJ~)=83eDvlWa=b zy|x6c2;?5&_iAByy?2Yl;qr*W2}TtiR8dYx#u?$g*P_q=x_*Q!0RV?Mc*pO+v4bM< zefIz5aZ-mZ3Eiz9q4XVf0Abi6wr6NMXQ(k+mBMC&8s|6l`DZ#QsGL#Zy}Q)b+`97} z3{0&9_>{%Pzj)E}FK|d2aJUCp3?=k(Bz=Gs#QE@acUj8k zH~e~eS=k;y4jA{w?|rW)=xVncH`4N=&DPg3XL*>Bk4ozM_oE##YamT&t68d>$H1uX zps)uA-$leFB)FW9JK!y2zwO|4qn|QI+EbC8S?1+P@?yh-jY_VK(JKBeP9I;n^!D}= zLImh?+c0&htp^I#EZ$Ub&pg@glBDe+Sw`f~joNEDwt7uUs~GeHEZ&lP@1KFk+xrq* z4rpq&YrFS+CO|bbHj)aK+?Z@Ct|W4cDiO1gE-a`s^>VD^v%e(i3)w*SFry|kl=e)n z?7DfXfd|0e&J<8}0DadGPdO zk00e#g|xmrG*L$U1j?imTC>8llo;MQOYd$@JrP*UKJ-%0A8&)l`*QcK{lnc_X3FFf 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%0D_{nu`9{} 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 DX*Z}P From 9e10cd690d5b061da2b54cd309b6bc3fc9ac6f3c Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Wed, 24 Apr 2024 02:42:50 +0000 Subject: [PATCH 102/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ast/strings.xml | 640 +++++++++++++++++++ app/src/main/res/values-b+en+001/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 3 +- 3 files changed, 643 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/values-ast/strings.xml diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml new file mode 100644 index 000000000000..ca5a3aeff86c --- /dev/null +++ b/app/src/main/res/values-ast/strings.xml @@ -0,0 +1,640 @@ + + + Aplicación %1$s p\'Android + Tocante + versión %1$s + Iconu de la cuenta + Editar + Balerar la papelera + Vista de rexella + Vista de llista + Carpeta nueva + Abrir con + Guetar + Detalles + Unviar + Axustes + Ordenar + Usuariu activu + Entá nun hai actividá + Unviar + Actividá + Amestar otru enllaz + Configuración avanzada + Buscar en: %s + Too + Escribi daqué + Falló + Planificóse + Completóse + Nun ye posible dir en cata de la llista de xeres. Comprueba la conexón a internet. + Nun ye posible dir en cata de los tipos de xeres. Comprueba la conexón a internet. + Asistente + Desconocí­u + Entrada + Salida + Yá esiste nel preséu una cuenta pal mesmu usuariu y sirvidor + L\'usuariu inxertáu nun concasa col usuariu d\'esta cuenta + Versión del sirvidor non reconocida + Conexón afitada + Nun s\'alcontró\'l sirvidor + Ensin conexón de rede + Conexón segura non disponible + Configuración del sirvidor mal fecha + Autorización ensin ésitu + Accesu refugáu pol sirvidor d\'autenticación + Conexón segura redirixida pente una ruta insegura. + Afitada conexón segura + Falló la inicialización SSL + Nun pudo verificase la identidá del sirvidor SSL + Probando conexón + El sirvidor tardó muncho en responder + Nome d\'usuariu o contraseña erroneos + ¡Asocedió un fallu desconocíu! + Nun pudo alcontrase l\'agospiu + %1$s nun permite cuentes múltiples + Nun pudo afitase la conexón + Avatar + Ausente + Zarrar + Desactivar + Calendariu + Calendarios + Hai un problema cargando\'l certificáu + Caxellu + Nun se puen borrar los avisos. + Borrar el mensaxe del estáu + Borrar el mensaxe l\'estáu dempués de + Testu copiáu dende %1$s + Copióse l\'enllaz + Atrás + Encaboxar + Encaboxar sincronización + Esbillar cuenta + Confirmar + Copiar + Desaniciar + Error + Nun hai abonda memoria + Fallu desconocíu + Cargando… + Siguiente + Non + Aceutar + Pendiente + Desaniciar + Renomar + Guardar + Unviar + Compartir + Saltar + Cambiar de cuenta + + Traducir + Namái llocal + Ficheru llocal + Contautos + Copióse nel cartafueyu + Asocedió un fallú entrín s\'intentaba copiar esta carpeta o ficheru + El ficheru yá ta presente na carpeta destín + Nun ye posible copiar. Comprueba si\'l ficheru esiste. + Copiar enllaz + Crear + Nun pudo crease la carpeta + Crear una carpeta + Desaniciar cuenta + Nun hai nenguna información disponible + Nun hai nengún anovamientu disponible. + Zarrar + Esti algorítmu de dixestión nun ta disponible nel tu teléfonu. + Desactivar + Escartar + Escargar l\'avisu + Nun molestar + Ficheru PDF + Xenerando\'l PDF… + Fecho + Nun borrar + Nun se pue crear el ficheru llocal + El nome ye inválidu pal ficheru llocal + Baxar la última versión de desendolcu + Nun pudo baxase %1$s + La descarga falló, volvi aniciar la sesión + Descarga fallida + Esti ficheru yá nun ta nel sirvidor + %1$d%% %2$s + %1$d%% Descargando %2$s + Baxando… + %1$s descargáu + Prodúxose un error mentanto se baxaben los ficheros + Entá non baxáu + Prodúxose un error inesperáu mentanto se baxaben los ficheros + Zarrar la barra llateral + Comunidá + Imaxe del fondu de la testera del caxón + Actividaes + Tolos ficheros + Asistente + Favoritos + Multimedia + Aniciu + Avisos + Nel preséu + Ficheros personales + Modificao apocayá + Compartío + Ficheros desaniciaos + Xubes + Zarrar la sesión + Abrir la barra llateral + %1$s de %2$s usao + %1$s n\'usu + Xuba automática + E2E nun ta configuráu + Nun ye posible ensin la conexón a internet + Asistente + Más + Notes + Charra + Más aplicaciones de Nextcloud + Nextcloud Notes + Nextcloud Talk + Nun se pue escoyer la direición de corréu electrónicu. + Configurar el cifráu + Descifrando… + Zarrar + Introduz la contraseña pa descrifrar la clave privada. + Esta carpeta nun ta balera. + Xenerando les claves nueves… + Contraseña… + Recuperando les claves… + Configurar el cifráu + Nun se pudieron guardar les claves, volvi tentalo. + Hebo un error mentanto se descifraba. ¿La contraseña ye incorreuta? + Introduz el nome del ficheru de destín + Introduz un nome pal ficheru + Nun se pudo copiar %1$s al ficheru llocal %2$s + Fallu críticu: Nun puen facese les operaciones + Hebo un error al escoyer la data + Hebo un error al comentar el ficheru + «%1$s» cascó + Hebo un error al crear a partir de la plantía + Hebo un error al amosar les aiciones el ficheru + Hebo un error al camudar l\'estáu del bloquéu + Informar + Hebo un error al recuperar el ficheru + Hebo un error al recuperar les plantíes + ¡Hebo un error al amosar el diálogu de configuración del cifráuª + Hebo un error al aniciar la cámara + Hebo un error al aniciar l\'escanéu del documentu + Cuentes + Nome del trabayu + Progresu + Estáu + Usuariu + UUID + Trabayos en segundu planu + Aniciar esti trabayu de prueba + Parar el trabayu de prueba + Preferencies + Tresferencia de ficheros + Camín remotu + Tresferir + Baxar + Xunir + Amestar o xubir + Nun se pue pasar el ficheru al xestor de descargues + Nun se pue imprentar el ficheru + Nun se pue aniciar l\'editor + Nun se pue anovar la IU + Meter en Favoritos + Meter en Favoritos + El nome yá esiste + Desaniciar + Hebo un error al recuperar les activadaes pal ficheru + Nun se puen cargar les detalles + Ficheru + Caltener + Nun se metió nada en Favoritos + Equí apaecen los ficheros y carpete que metas en Favoritos. + Equí nun hai ficheros + Ensin resultaos nesta carpeta + Ensin resultaos + Equí nun hai nada. Pes amestar una carpeta + ¿Quiciabes tea nuna carpeta diferente? + Entá nun se compartió nada + Nun s\'atopó nengún resultáu pa la to consulta + Carpeta + EN DIREUTO + Cargando… + Nun s\'afitó una aplicación pa remanar esta triba de ficheru. + hai segundos + Precísense permisos + Permisos d\'almacenameintu + Comprobando\'l destín… + Precísase más espaciu + Nun se pudo lleer el ficheru d\'orixe + Nun se pudo escribir nel ficheru de destín + Nun se pue anovar l\'índiz + Moviendo los datos… + Finó + Trocar + Restaurando la configuración de la cuenta… + Guardando la configuración de la cuenta… + ¡Nun se pue lleer la carpeta d\'orixe! + Anovando l\'índiz… + Usar + Esperando la sincronización completa… + Nun s\'atopó\'l ficheru + El ficheru nun se pudo sincronizar. Amuésase la última versión disponible + Renomar + ¡Hebo un error al restaurar la versión del ficheru! + Detalles + Descargar + Esportar + Sincronizar + Nun s\'esbillaron ficheros + El nome del ficheru nun pue tar baleru. + Caráuteres prohibíos: / \\ < > : \" | ? * + El nome del ficheru contién polo menos un caráuter inváldu + Nome del ficheru + La carpeta yá esiste + Crear + Equí nun hai nenguna carpeta + Escoyer + Escoyer la carpeta de destín + Copiar + Mover + Nun tienes permisu %s + pa copiar esti ficheru + pa crear esti ficheru + pa desaniciar esti ficheru + pa mover esti ficheru + pa renomar esti ficheru + Xubiendo los ficheros… + Nun se pudieron copiar dalgunos ficheros + Llocal: %1$s + Mover too + Llugar remotu: %1$s + Moviéronse tolos ficheros + Avanzar + 4 hores + Esti iconu amuesa la disponibilidá de la semeya en direuto + Nome + Nota + Contraseña + El sirvidor nun ta disponible + L\'agospiador del to sirvidor + Nun ye posible editar la imaxe. + ƒ/%s + ISO %s + %s MP + %s mm + %s s + na carpeta %1$s + Namái xubir al cargar + /XubidaNelIntre + La URL ye inválisa + Invisible + La etiqueta nun pue tar baleru + Enllaz + Nome del enllaz + Permitir la xuba y la edición + Suelta de ficheros (namás xuba) + Ver namás + Cargar más resultaos + Nun hai ficheros nesta carpeta. + %1$s/%2$s + Nun hai más carpetes. + Data de caducidá: %1$s + Aplicación de rexistros d\'Android %1$s + Aniciar la sesión + Anovar + Cargando… + Llimpiar datos + Alministrar espaciu + Nun pudo lleese\'l ficheru de medios + El ficheru de medios tien una codificación incorreuta + Escoso\'l tiempu pa reproducir el ficheru + El reproductor multimedia integráu nun ye a reproducir el ficheru + Códec multimedia non soportáu + Botón d\'avance rápidu + Botón de reproducción o posa + Botón de rebobináu + Lo más nuevo + Lo más vieyo + A - Z + Z - A + Lo más grande + Lo más pequeño + Más + Asocedió un fallu entrín s\'intentaba mover esta carpeta + Nun ye posible mover una carpeta a les sos soxacentes + El ficheru yá ta presente na carpeta de destín + Nun ye posible mover el ficheru. Comprueba si esiste. + Comentariu nuevu… + semeya + videu + Avisu nuevu + Creóse la versión + Nun hai nenguna aición pa esti usuariu + Nun hai nenguna aplicación pa remanar esto + Nun esiste nengún calendariu + Nun hai nenguna aplicación pa remanar esta direición de corréu electrónica + Nun hai nengún elementu + Nun s\'atopón nenguna aplicación pa remanar mapes + Namás se permite una cuetna + Nun hai nenguna aplicación disponible pa remanar PDF + Nun hai nenguna aplicación disponible pa unviar los ficheros seleicionaos + Seleiciona polo menos un permisu pa compartir + Nun se pudo unviar la nota + Iconu de la nota + Nun se pue executar l\'aición. + Amuesa\'l progresu de la descarga + Descargués + Amuesa\'l progresu y los resultaos de la sincronización de ficheros + Sincronización de ficheros + Avisos xenerales + Progresu del reproductor de música + Reproductor multimedia + Avisos push + Amuesa\'l progresu de la xuba + Xubes + Ensin avisos + Volvi equí dempués. + Nun hai conexón a internet + 1 hora + En llinia + Estáu en llinia + El sirvidor algamó la fin de vida. ¡Anueva! + Menú de Más + Introduz el to códigu de pasu + La contraseña va ser solicitada cada vegada que s\'anicie l\'aplicación + Introduz el to códigu de pasu, por favor + Les contraseñes nun son les mesmes + Por favor, vuelvi inxertar la contraseña + Desaniciar el códigu d\'accesu + Desanicióse\'l códigu d\'accesu + Contraseña almacenada + Contraseña incorrecta + Nun ye posible abrir el PDF protexíu con contraseña. Usa un visor de PDFs esternu. + Toca nuna páxina p\'averar + Permitir + Negar + Ríquense permisos adicionales pa xubir y baxar ficheros. + Abrir «%1$s» + 389 KB + MarcadorDePosicion.txt + 12:23:45 + Esto ye un marcador de posición + 2012/05/18 12:23 PM + desanicióse + guardáu en carpeta orixinal + movíu a la carpeta d\'aplicaciones + ¿Qué faigo que\'l ficheru yá esiste? + Saltar la xuba + Sobrescribir la versión remota + Renomar la versión nueva + ¿Qué faigo que\'l ficheru yá esiste? + Amestar cuenta + Tocante a + Detalles + Xeneral + Más + Ayuda + Usar socarpetes + Llicencia + Nada + Còdigu d\'accesu + Xestionar cuentes + Quitar llocalmente\'l cifráu + Amosar el conmutador d\'aplicaciones + Amosar ficheros anubríos + Consiguir el códigu fonte + Carpeta llocal + Carpeta remota + Estilu + Escuridá + Claridá + Previsualización d\'imaxe + Nun pue amosase la imaxe + Sentímoslo + Privacidá + Nome nuevu + ¡Nun se pudo lleer el códigu QR! + ¡Prueba %1$s nel preséu! + %1$s o %2$s + Anovar el conteníu + Volver cargar + (remotu) + ¡Nun se pue atopar el ficheru! + Pues quitar el cifráu d\'estremu a estremu llocalmente nesti veceru + El desaniciu falló + Quitar la cuenta llocal + Quitar la cuenta del preséu y desaniciar tolos ficheros llocales + Nun se pue quitar l\'avisu. + Quitar + Desanicióse + Introduz un nome nuevu + Nun se pudo renomar la copia llocal, prueba con otru nome + El cambéu de nome nun ye posible, el nome yá ta n\'usu + Solicitar el desaniciu de la cuenta + Solicitar el desaniciu + Nun se pue volver compartir + Nun se pue volver compartir + Restaurar el ficheru + Restaurar el ficheru desainiciáu + Recuperando\'l ficheru… + ¡Nun se pue cargar el documentu! + Aniciar la sesión per QR + Escaniar la páxina + nun llugar + Xuba automática + pa les semeyes y vídeos + Calendariu y contautos + Hebo un error al consiguir los resultaos de busca + Esbillar too + Unviar + Afitar l\'estáu + Afitar el mensaxe del estáu + Compartir + Compartiendo + %1$s + Compartir %1$s + %1$s (gropu) + Compartir l\'enllaz internu + Compartir l\'enllaz + Tienes qu\'introducir una contraseña + Nun ye posible compartir. Comprueba si\'l ficheru esiste. + pa compartir esti ficheru + Introduz una contraseña + Afitar la data de caducidá + Afitar la contraseña + Pue editar + Suelta de ficheros + Ver namás + %1$s (remotu) + %1$s (conversación) + Nota al destinatariu + Configuración + Anubrir la descarga + Compartir enllaz + Unviar l\'enllaz + Amosar les semeyes + Amosar los vídeos + Rexistrase con un fornidor + ¿Quies permitr que %1$s acceda a la cuenta de Nextcloud %2$s? + Ordenar per + Anubrir + Detalles + Nun se pudo verificar la identidá del sirvidor + País: + Nome común: + Llocalización: + Organización: + Unidá organizativa: + Estáu: + Robla + Emitíu por: + Robla: + Algoritmu: + Emitíu pa: + Validez: + De: + A: + - Nun atopamos información tocante a esti fallu + Nun pudo guardase\'l certificáu + Nun pudo amosase\'l certificáu. + ¿Quies enfotate nesti certificáu de toes formes? + - El certificáu del sirvidor caducó + - El certificáu del sirvidor nun ye de confianza + - Les dates de validez del certificáu tán nel futuru + - La URL nun casa col nome del sirvidor nel certificáu + Mensaxe del estáu + Cámara + Por defeutu + Documentos + Descargués + Almacenamientu internu + Filmes + Música + Accesu completu + Semeyes + Añu/Mes/Día + Añu/Mes + Añu + Compartiose \"%1$s\" contigo + %1$s compartío \"%2$s\" contigo + Namás les semeyes + Semeyes y vídeos + Namás los vídeos + Suxerir + Conflictos alcontraos + La carpeta %1$s yá nun esiste + Nun se pudo sincronizar «%1$s» + Contraseña incorreuta pa %1$s + Fallu al caltener ficheros sincronizaos. + Sincronización fallida + La sincronización fallo, volvi aniciar la sesión + El conteníu del ficheru yá ta sincronizáu + Dexáronse dalgunos ficheros llocales. + Nun hai abondu espaciu + Ficheros + Botón de Configuración + Configurar les carpetes + Nun s\'atopó nenguna carpeta multimedia + Pa %1$s + Tipu + Etiquetes + Probar la conexón del sirvidor + 30 minutos + Esta selmana + Miniatura + Güei + Ficheros desaniciaos + Nun hai nengún ficheros desnaiciáu + ¡Nun se pudo restaurar el ficheru «%1$s»! + Desaniciar permanentemente + ¡La carga de la papelera falló! + ¡Los ficheros nun se pudieron desaniciar permanentemente! + Desbloquiar el ficheru + Esisten comentarios ensin lleer + Quitar de Favoritos + Prodúxose un error mentanto se dexaba de compartir esti ficheru o esta carpeta + Nun ye posible dexar de compartir. Comprueba si\'l ficheru esiste. + pa dexar de compartir esti ficheru + Nun ye posible anovar. Comprueba si\'l ficheru esiste. + p\'anovar esta compartición + Siguir coles descargues anulaes + Posar toles descargues + Siguir con toles descargues + Nun se pue crear el ficheru llocal + Nome de ficheru + Triba de ficheru + Toles descargues tán posaes + Desaniciar + Nun hai xubes disponibles + Error desconocíu + Escoyer + Xubir + Los datos recibíos nun inclúin un ficheru válidu. + %1$s nun tien permisu pa lleer un ficheru recibíu + Nun pudo copiase\'l ficheru a una carpeta temporal. Prueba a reunvialu. + Esti ficheru nun se pue xubir + Ensin ficheru pa xubir + Nome de la carpeta + Escueyi una carpeta de xuba + Nun pudo xubise %1$s + Xuba fallida + Opción de xuba: + Caltener ficheru na carpeta fonte + pa xubir esta carpeta + %1$d%% %2$s + %1$d%% Xubiendo %2$s + Xubiendo… + %1$s xubíu + Colar + Configuración + Nun hai nenguna cuenta %1$s nel to preséu. Por favor configura una cuenta enantes. + Nun s\'alcontraron cuentes + Actual + Xubíu + Encaboxáu + Esperando pa xubir + Xubes + Encaboxáu + Conflictu + Fallu de conexón + Fallu de credenciales + Fallu de ficheru + Fallu de carpeta + Ficheru llocal nun s\'atopó + Fallu de permisu + Diendo en cata de la versión del sirvidor… + Aplicación finada + Completáu + Fallu desconocíu + Detectóse un virus. ¡Nun se pue completar la xuba! + Usuariu + Direición + Corréu electrónicu + Númberu telefónicu + Twitter + Sitiu web + Hebo un error al recuperar la información del usuariu + Nome d\'usuariu + Baxar + Espera un momentu… + Comprobación de credenciales almacenaes + Copiando ficheru dende l\'almacenamientu priváu + Anovar + Saltar + ¿Cuál ye\'l to estáu? + Nun ta disponible + Baxando los ficheros… + Unviar un corréu electrónicu + + %d na seleición + %d na seleición + + diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 27c89263b58d..8d57743fb01e 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -354,7 +354,7 @@ File Keep Upload some content or sync with your devices. - Nothing favourited yet + Nothing has been marked as favourite yet Files and folders you mark as favorites will show up here. Found no images or videos No files here diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 37eaac6a932a..41dfd4f27cda 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -172,6 +172,7 @@ Ви справді бажаєте вилучити %1$s та його вміст? Дійсно вилучити вибрані об\'єкти та їхній вміст? Лише на пристрої + Неможливо ініціювати діалог розв\'язання конфлікту Конфліктний файл %1$s Файл на пристрої Якщо ви виберете обидві версії, то до назви локального файлу буде додано порядковий номер. @@ -261,7 +262,7 @@ Старт Сповіщення На пристрої - Приватні файли + Мої документи Нещодавно змінені Спільні Кошик From 90b3958894df952c0e0e0580734b3768ee3b9e84 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 24 Apr 2024 07:21:10 +0200 Subject: [PATCH 103/114] fix test Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/utils/theme/CapabilityUtilsIT.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/theme/CapabilityUtilsIT.kt b/app/src/androidTest/java/com/owncloud/android/utils/theme/CapabilityUtilsIT.kt index 0746c4dd845b..98b410f6707d 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/theme/CapabilityUtilsIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/theme/CapabilityUtilsIT.kt @@ -17,11 +17,12 @@ import org.junit.Test class CapabilityUtilsIT : AbstractIT() { @Test fun checkOutdatedWarning() { + assertFalse(test(NextcloudVersion.nextcloud_28)) assertFalse(test(NextcloudVersion.nextcloud_27)) - assertFalse(test(NextcloudVersion.nextcloud_26)) - assertFalse(test(NextcloudVersion.nextcloud_25)) - assertFalse(test(NextcloudVersion.nextcloud_24)) + assertTrue(test(NextcloudVersion.nextcloud_26)) + assertTrue(test(NextcloudVersion.nextcloud_25)) + assertTrue(test(NextcloudVersion.nextcloud_24)) assertTrue(test(NextcloudVersion.nextcloud_23)) assertTrue(test(NextcloudVersion.nextcloud_22)) assertTrue(test(NextcloudVersion.nextcloud_21)) From 0334871f64c262554e531d0edb0938edc7548cf8 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 24 Apr 2024 08:58:20 +0200 Subject: [PATCH 104/114] Add changelog for 3.29.0 Signed-off-by: tobiasKaminsky --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97df73bf1dba..a8b57bed0453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +# +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2024 Tobias Kaminsky +# SPDX-License-Identifier: AGPL-3.0-or-later +# + +## 3.29.0 (April 24, 2024) + +- NC Assistant +- Client certificates +- Personal files view +- REUSE compliance +- Bugfixes + + +Minimum: NC 16 Server, Android 7.0 Nougat + +For a full list, please see https://github.com/nextcloud/android/milestone/89 + ## 3.28.2 (April 4th, 2024) - Bugfixes From 92392d49a7fafdee09f2c3195977172fab8e73d2 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 25 Apr 2024 18:02:42 +0200 Subject: [PATCH 105/114] fix: spdx header position Signed-off-by: Andy Scherzinger --- CHANGELOG.md | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8b57bed0453..aa3bbc8d25e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -# -# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-FileCopyrightText: 2024 Tobias Kaminsky -# SPDX-License-Identifier: AGPL-3.0-or-later -# + ## 3.29.0 (April 24, 2024) @@ -12,7 +12,6 @@ - REUSE compliance - Bugfixes - Minimum: NC 16 Server, Android 7.0 Nougat For a full list, please see https://github.com/nextcloud/android/milestone/89 @@ -21,16 +20,10 @@ For a full list, please see https://github.com/nextcloud/android/milestone/89 - Bugfixes - Minimum: NC 16 Server, Android 7.0 Nougat For a full list, please see https://github.com/nextcloud/android/milestone/90 - - ## 3.28.1 (March 25th, 2024) - Bugfixes @@ -44,7 +37,6 @@ For a full list, please see https://github.com/nextcloud/android/milestone/90 - E2E sharing - Bugfixes - Minimum: NC 16 Server, Android 7.0 Nougat For a full list, please see https://github.com/nextcloud/android/milestone/88 From bbe218a265d4e423b38062eb54c062831b10742b Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Thu, 25 Apr 2024 18:24:16 +0200 Subject: [PATCH 106/114] Have correct SPDX license header for logo/trademarked items Signed-off-by: Andy Scherzinger --- .reuse/dep5 | 4 ++-- LICENSES/LicenseRef-NextcloudTrademarks.txt | 9 +++++++++ app/src/main/res/drawable/ic_launcher_foreground.xml | 5 ++--- app/src/main/res/drawable/logo.xml | 5 ++--- 4 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 LICENSES/LicenseRef-NextcloudTrademarks.txt diff --git a/.reuse/dep5 b/.reuse/dep5 index 1babbb7e974e..acdbfdc008a4 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -20,8 +20,8 @@ Copyright: 2015-2016 ownCloud Inc. License: GPL-2.0-only Files: app/src/*/res/mipmap-*dpi/ic_launcher.png app/src/*/ic_launcher-web.png src/generic/fastlane/metadata/android/en-US/images/icon.png src/versionDev/fastlane/metadata/android/en-US/images/icon.png app/src/main/ic_launcher-web-round.png -Copyright: 2017-2024 Nextcloud GmbH. All rights reserved. Trademarks apply, see https://nextcloud.com/trademarks/ -License: AGPL-3.0-or-later +Copyright: 2017-2024 Nextcloud GmbH +License: LicenseRef-NextcloudTrademarks Files: .idea/* app/schemas/com.nextcloud.client.database.NextcloudDatabase/*.json app/screenshots/gplay/debug/*.png app/src/main/res/values-*/strings.xml src/*/fastlane/metadata/android/*/*.txt src/versionDev/fastlane/metadata/android/*/changelogs/*.txt app/src/androidTest/assets/* app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker app/src/*/google-services.json app/src/main/res/drawable-*dpi/checker_16_16.png app/src/main/res/raw/encryption_key_words.txt app/src/main/resources/ical4j.properties app/src/main/res/drawable-*dpi/apk.png app/src/main/res/drawable-*dpi/fdroid.png app/src/main/res/drawable-*dpi/playstore.png app/src/main/res/drawable-*dpi/background.png app/src/main/res/drawable-*dpi/background_nc18.png Copyright: 2016-2024 Nextcloud GmbH and Nextcloud contributors diff --git a/LICENSES/LicenseRef-NextcloudTrademarks.txt b/LICENSES/LicenseRef-NextcloudTrademarks.txt new file mode 100644 index 000000000000..464a30b58bdc --- /dev/null +++ b/LICENSES/LicenseRef-NextcloudTrademarks.txt @@ -0,0 +1,9 @@ +The Nextcloud marks +Nextcloud and the Nextcloud logo is a registered trademark of Nextcloud GmbH in Germany and/or other countries. +These guidelines cover the following marks pertaining both to the product names and the logo: “Nextcloud” +and the blue/white cloud logo with or without the word Nextcloud; the service “Nextcloud Enterprise”; +and our products: “Nextcloud Files”; “Nextcloud Groupware” and “Nextcloud Talk”. +This set of marks is collectively referred to as the “Nextcloud marks.” + +Use of Nextcloud logos and other marks is only permitted under the guidelines provided by the Nextcloud GmbH. +A copy can be found at https://nextcloud.com/trademarks/ diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index b15a7699c382..0235efa7e6fb 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,9 +1,8 @@ - ~ SPDX-License-Identifier: AGPL-3.0-or-later + ~ SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH + ~ SPDX-License-Identifier: LicenseRef-NextcloudTrademarks --> Date: Fri, 26 Apr 2024 02:22:05 +0000 Subject: [PATCH 107/114] =?UTF-8?q?=F0=9F=94=84=20synced=20local=20'.githu?= =?UTF-8?q?b/workflows/'=20with=20remote=20'config/workflows/'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nextcloud-android-bot --- .github/workflows/analysis.yml | 2 +- .github/workflows/codeql.yml | 6 +++--- .github/workflows/gradle-wrapper-validation.yml | 4 ++-- .github/workflows/scorecard.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index da4708f09809..47b48ecad89f 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -44,7 +44,7 @@ jobs: echo "repo=${{ github.event.pull_request.head.repo.full_name }}" } >> "$GITHUB_OUTPUT" fi - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: repository: ${{ steps.get-vars.outputs.repo }} ref: ${{ steps.get-vars.outputs.branch }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 850dc0ca0ab3..2564164fb4da 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,13 +33,13 @@ jobs: language: [ 'java' ] steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Set Swap Space uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0 with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -53,4 +53,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 0d0251be187d..b72bf62069be 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -25,5 +25,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - - uses: gradle/wrapper-validation-action@5188e9b5527a0a094cee21e2fe9a8ca44b4629af # v3.3.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: gradle/wrapper-validation-action@216d1ad2b3710bf005dc39237337b9673fd8fcd5 # v3.3.2 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4074e5b0c3d7..4507aadd13bc 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: persist-credentials: false @@ -42,6 +42,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif From 3644710cc696adf4f8148eb299a439e188d443a2 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 26 Apr 2024 02:45:46 +0000 Subject: [PATCH 108/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-tr/strings.xml | 3 ++- app/src/main/res/values-uk/strings.xml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index e2c1d451f4ec..91c82f0b948e 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -57,7 +57,7 @@ Yardımcı Bilinmiyor Giriş - Çıktı + Çıkış İlişkili hesap bulunamadı! Erişilemedi: %1$s Aygıt üzerinde henüz bu hesap açılmamış @@ -172,6 +172,7 @@ %1$s klasörünü ve içindekileri silmek istediğinize emin misiniz? Seçilmiş ögeleri ve içindekileri silmek istediğinize emin misiniz? Yalnızca yerel + Çakışma çözümleme penceresi oluşturulamadı %1$s dosyası çakışıyor Yerel dosya İki sürümü de saklamayı seçerseniz, yerel dosyanın adına bir numara eklenecek. diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 41dfd4f27cda..1f26463e95b2 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -254,7 +254,7 @@ Спільнота Зображення тла верхньої панелі Події - Усі файли + Усі документи Помічник Із зірочкою Зображення та відео @@ -354,7 +354,7 @@ Поки що ви нічого не позначили зірочкою Тут можна буде знайти файли та каталоги, які ви позначити зірочкою. Не знайдено ані зображень, ані відео - Тут немає файлів + Тут відсутні файли Жодного збігу у цьому каталозі Жодного збігу Тут нічого немає. Ви можете створити каталог. From 724115de3e58742cdfb50986d45e0b11a999f766 Mon Sep 17 00:00:00 2001 From: Unpublished Date: Sun, 14 Apr 2024 15:37:12 +0200 Subject: [PATCH 109/114] Show snackbar above FAB Signed-off-by: Unpublished --- ...ileFragmentTest_displayJavaSnippetFile.png | Bin 31094 -> 31415 bytes ...FileFragmentTest_displaySimpleTextFile.png | Bin 15155 -> 15735 bytes .../owncloud/android/utils/DisplayUtils.java | 16 ++++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/app/screenshots/gplay/debug/com.owncloud.android.ui.preview.PreviewTextFileFragmentTest_displayJavaSnippetFile.png b/app/screenshots/gplay/debug/com.owncloud.android.ui.preview.PreviewTextFileFragmentTest_displayJavaSnippetFile.png index 4b8e5ba28034728c574b19a0f2a0751898e62fe8..66db64e770d817505c7011fad2dd5655c64ff2cf 100644 GIT binary patch delta 4859 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 GFaHZx%?Q%~ delta 4366 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 Dd2lfo diff --git a/app/screenshots/gplay/debug/com.owncloud.android.ui.preview.PreviewTextFileFragmentTest_displaySimpleTextFile.png b/app/screenshots/gplay/debug/com.owncloud.android.ui.preview.PreviewTextFileFragmentTest_displaySimpleTextFile.png index bba71fe6886dd6ae0cbc5aa57022815b4b9b731a..555930077547910fe1c5c6589f44edd85c338299 100644 GIT binary patch literal 15735 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 WJuq4u0~Et Date: Fri, 26 Apr 2024 14:52:46 +0200 Subject: [PATCH 110/114] Improve screen tests? Signed-off-by: Unpublished --- .github/workflows/screenShotTest.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/screenShotTest.yml b/.github/workflows/screenShotTest.yml index 8a2c755599b2..27ba4ad706f4 100644 --- a/.github/workflows/screenShotTest.yml +++ b/.github/workflows/screenShotTest.yml @@ -17,7 +17,7 @@ concurrency: jobs: screenshot: - runs-on: macOS-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -48,6 +48,12 @@ jobs: distribution: "temurin" java-version: 17 + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # v2.30.1 From bca6d3781026fba10097343c3ab08b4a818fdfc1 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 26 Apr 2024 17:28:56 +0000 Subject: [PATCH 111/114] Updating reuse.yml workflow from template Signed-off-by: Nextcloud bot --- .github/workflows/reuse.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 0d92e5efe1ae..57231dcf6cec 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -1,4 +1,7 @@ -# synced from @nextcloud/android-config +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization # SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. # @@ -6,12 +9,12 @@ name: REUSE Compliance Check -on: [push, pull_request] +on: [pull_request] jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: REUSE Compliance Check uses: fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 # v3.0.0 From 59370298d6666b09ddc898bbf03d69ac1dcee1bb Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 26 Apr 2024 17:53:19 +0000 Subject: [PATCH 112/114] Updating pr-feedback.yml workflow from template Signed-off-by: Nextcloud bot --- .github/workflows/pr-feedback.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-feedback.yml b/.github/workflows/pr-feedback.yml index e5fe74a04ee3..940eda2317ca 100644 --- a/.github/workflows/pr-feedback.yml +++ b/.github/workflows/pr-feedback.yml @@ -3,7 +3,7 @@ # https://github.com/nextcloud/.github # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization -# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors # SPDX-FileCopyrightText: 2023 Marcel Klehr # SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com> # SPDX-FileCopyrightText: 2023 Daniel Kesselberg From fa742a76630799bfa0e59262ea141fbd220a1df2 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sat, 27 Apr 2024 02:52:26 +0000 Subject: [PATCH 113/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-ja-rJP/strings.xml | 3 +++ app/src/main/res/values-sk-rSK/strings.xml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 30c83eff3f99..c3d2d087df6d 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -37,9 +37,12 @@ ダッシュボードから一つのウィジェットを表示 %s の中を検索 すべて + テキストを入力 失敗 完了 不明 + 入力 + 出力 関連付けられたアカウントが見つかりません! アクセスに失敗しました: %1$s このアカウントはまだこのデバイスに追加されていません diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 2d9d9fcf03a7..39c4efe7cb84 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -56,6 +56,8 @@ Nie je možné načítať typy úloh, skontrolujte svoje internetové pripojenie. Asistent Neznámy + Vstup + Výstup Priradený účet sa nenašiel Prístup zamietnutý: %1$s Účet zatiaľ v zariadení neexistuje @@ -170,6 +172,7 @@ Naozaj chcete odstrániť %1$s a jeho obsah? Naozaj chcete odstrániť vybraté položky a ich obsah? Iba lokálne + Dialógové okno riešenia konfliktov nemožno vytvoriť Konfliktný súbor %1$s Lokálny súbor Ak vyberiete obe verzie, miestny súbor bude mať k svojmu názvu pridané číslo. From 619ae12f143e5a95dbbfbb96283b943062cc1fc5 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Sun, 28 Apr 2024 02:45:39 +0000 Subject: [PATCH 114/114] Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- app/src/main/res/values-in/strings.xml | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 2fbc92625e05..0032cd0c8408 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -13,6 +13,7 @@ Kirim/Bagi Tampilan kotak Tampilan lis + Pulihkan kontak dan kalender Folder baru Pindah atau Salin Buka dengan @@ -32,10 +33,30 @@ Tambahkan ke %1$s Pengaturan Tambahan Izinkan pembagian ulang + Menampilkan satu gawit dari dasbor Cari dalam %s Semua + Tulis beberapa teks + Apakah Anda yakin ingin menghapus tugas ini? + Hapus Tugas + Gagal + Daftar Tugas sedang dimuat, mohon tunggu + Tidak ada tugas yang tersedia. Pilih jenis tugas untuk membuat tugas baru. + Tidak ada tugas yang tersedia untuk jenis tugas %s, Anda dapat membuat tugas baru dari pojok kanan bawah. + Sedang Berlangsung + Dijadwalkan Selesai + Terjadi kesalahan saat membuat tugas + Tugas berhasil dibuat + Terjadi kesalahan saat menghapus tugas + Tugas berhasil dihapus + Tidak dapat memperoleh daftar tugas, mohon periksa koneksi internet Anda. + Hapus Tugas + Tidak dapat memperoleh jenis tugas, mohon periksa koneksi internet Anda. + Asisten Tidak diketahui + Input + Output Akun terkait tidak ditemukan! Akses gagal: %1$s Akun ini belum ditambahkan ke perangkat ini @@ -74,9 +95,11 @@ Pasang folder kostum. Non-aktifkan pemeriksaan mode hemat daya Sembunyikan folder + Menyiapkan unggah otomatis Avatar Jauh Pengaturan Pencadangan + Pencadangan kontak dan kalender Tutup Nonaktifkan Optimisasi baterai perangkat Anda mungkin sedang aktif. @@ -87,11 +110,13 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Kalender Terjadi permasalahan memuat sertifikat. Perubahan versi dev + Periksa kembali nanti atau muat ulang. Kotak centang Pilih folder lokal… Pilih folder remot… Mohon pilih templat dan masukkan nama file. Pilih file mana yang ditahan! + Pilih gawit Gagal membersihkan notifikasi Kosongkan status pesan Kosongkan status pesan setelah @@ -127,6 +152,7 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Ini termasuk semua fitur yang akan datang. Bug/galat bisa terjadi, bila terjadi harap laporkan ke kami. forum Bantu yang lain di + Tinjau, ubah, dan tulis kode, lihat %1$suntuk detailnya. Berkontribusi Aktif aplikasi Terjemahkan @@ -146,6 +172,7 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Apakah anda yakin ingin menghapus %1$s beserta isinya? Apa anda yakin ingin menghapus item yang terpilih beserta isinya? Lokal saja + Dialog penyelesaian konflik tidak dapat dibuat File konflik %1$s File lokal Jika Anda memilih kedua versi, nama dari berkas lokal akan ditambahi angka. @@ -218,18 +245,23 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Mengunduh… %1$s terunduh Unggahan + Berkas tertentu dibatalkan saat pengunduhan oleh pengguna + Terjadi kesalahan saat mengunduh berkas Belum diunduh + Terjadi kesalahan tidak terduga saat mengunduh berkas Tutup jendela samping Komunitas Gambar latar belakang tajuk laci Aktivitas Semua berkas + Asisten Disukai Media Folder kelompok Beranda Pemberitahuan Dalam perangkat + Berkas pribadi Baru diubah Dibagikan Berkas terhapus @@ -241,6 +273,7 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Unggah otomatis. E2E belum dipersiapkan Tidak bisa dilakukan tanpa koneksi internet + Asisten Lainnya Catatan Talk @@ -270,6 +303,7 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Terjadi kesalahan dalam memilih tanggal Error saat mengomentari file Galat saat membuat berkas dari templat + Kesalahan menampilkan aksi berkas Error saat mengubah status kunci file Laporan Galat saat menerima file @@ -278,6 +312,7 @@ Otomatis unggah hanya bekerja dengan baik apabila Anda mengeluarkan aplikasi ini Galat saat mengaktifkan kamera Galat memulai pemindaian dokumen Akun + Dibuat Nama pekerjaan Kemajuan Kondisi