diff --git a/app/src/main/java/com/nextcloud/android/files/FileLockingHelper.kt b/app/src/main/java/com/nextcloud/android/files/FileLockingHelper.kt index 5e3c7a66a964..ad685f961009 100644 --- a/app/src/main/java/com/nextcloud/android/files/FileLockingHelper.kt +++ b/app/src/main/java/com/nextcloud/android/files/FileLockingHelper.kt @@ -16,9 +16,15 @@ object FileLockingHelper { */ @JvmStatic fun canUserUnlockFile(userId: String, file: OCFile): Boolean { - if (!file.isLocked || file.lockOwnerId == null || file.lockType != FileLockType.MANUAL) { + if (!file.isLocked) { return false } - return file.lockOwnerId == userId + if (file.lockType == FileLockType.MANUAL && file.lockOwnerId == userId) { + return true + } + // App locks (Text, OnlyOffice, ...) carry no lock owner id and are reported as + // COLLABORATIVE. The file owner may still unlock them: LockService::canUnlock + // accepts any TYPE_USER request from the file owner. + return file.lockType != FileLockType.TOKEN && file.ownerId == userId } } diff --git a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt index 9ea47476ce89..200a2b24cd1f 100644 --- a/app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt @@ -128,10 +128,12 @@ class FileActionsBottomSheet : when (state) { is FileActionsViewModel.UiState.LoadedForSingleFile -> { loadFileThumbnail(state.titleFile) + // displayActions aborts when the action list is not empty, so it has to + // run before the lock info row is appended. + displayActions(state.titleFile, state.actions) if (state.lockInfo != null) { displayLockInfo(state.lockInfo) } - displayActions(state.titleFile, state.actions) displayTitle(state.titleFile) } diff --git a/app/src/test/java/com/nextcloud/android/files/FileLockingHelperTest.kt b/app/src/test/java/com/nextcloud/android/files/FileLockingHelperTest.kt index d105e99cfc8c..5e77e32da19b 100644 --- a/app/src/test/java/com/nextcloud/android/files/FileLockingHelperTest.kt +++ b/app/src/test/java/com/nextcloud/android/files/FileLockingHelperTest.kt @@ -34,6 +34,38 @@ class FileLockingHelperTest { Assert.assertFalse(FileLockingHelper.canUserUnlockFile(USER_NAME, file)) } + @Test + fun fileOwnerCanUnlockLockOfAnotherClient() { + val file = OCFile("/foo.md").apply { + isLocked = true + lockOwnerId = "text" + lockType = FileLockType.MANUAL + ownerId = USER_NAME + } + Assert.assertTrue(FileLockingHelper.canUserUnlockFile(USER_NAME, file)) + } + + @Test + fun fileOwnerCanUnlockAppLock() { + val file = OCFile("/foo.docx").apply { + isLocked = true + lockOwnerId = null + lockType = FileLockType.COLLABORATIVE + ownerId = USER_NAME + } + Assert.assertTrue(FileLockingHelper.canUserUnlockFile(USER_NAME, file)) + } + + @Test + fun fileOwnerCannotUnlockTokenLock() { + val file = OCFile("/foo.docx").apply { + isLocked = true + lockType = FileLockType.TOKEN + ownerId = USER_NAME + } + Assert.assertFalse(FileLockingHelper.canUserUnlockFile(USER_NAME, file)) + } + @Test fun typeNotManual_cannotUnlock() { val file = OCFile("/foo.md").apply {