From c04a23ea008834537ea91ab789be4cce0174b2a4 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 9 Feb 2022 14:51:22 +0100 Subject: [PATCH 001/102] make multiselect offline switch behave like IOS --- .../ActionMultiSelectBottomSheetDialog.kt | 5 ++- .../drive/ui/fileList/FileListFragment.kt | 34 ++++++++++++------- .../main/res/navigation/main_navigation.xml | 8 +++++ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 77797913f5..0b3ffd37ef 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -73,7 +73,10 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } private fun configureAvailableOffline(otherActionsVisibility: Boolean) { - availableOfflineSwitch.setOnCheckedChangeListener { _, _ -> onActionSelected(SelectDialogAction.OFFLINE) } + availableOfflineSwitch.apply { + isChecked = navigationArgs.onlyOffline + setOnCheckedChangeListener { _, _ -> onActionSelected(SelectDialogAction.OFFLINE) } + } disabledAvailableOffline.isVisible = navigationArgs.onlyFolders availableOffline.apply { setOnClickListener { onActionSelected(SelectDialogAction.OFFLINE) } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index c976034f56..02fc12473e 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -436,6 +436,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } BulkOperationType.SET_OFFLINE -> { addSelectedFilesToOffline(file) + closeMultiSelect() } BulkOperationType.ADD_FAVORITES -> { mediator.addSource( @@ -478,7 +479,8 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { fileIds = fileAdapter.getValidItemsSelected().map { it.id }.toIntArray(), onlyFolders = fileAdapter.getValidItemsSelected().all { it.isFolder() }, ) - ) + } + } selectAllButton.apply { @@ -653,21 +655,29 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } private fun addSelectedFilesToOffline(file: File) { - if (!file.isOffline && !file.isFolder()) { + if (!file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) - - if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { - Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) - runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } - - fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> - if (currentFile.isNotManagedByRealm()) { - currentFile.isOffline = true - currentFile.currentProgress = 0 + if (file.isOffline) { + lifecycleScope.launch { + if (offlineFile != null) { + mainViewModel.removeOfflineFile(file, offlineFile, cacheFile) + file.isOffline = false } } - } else Utils.downloadAsOfflineFile(requireContext(), file) + } else { + if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { + Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) + runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } + + fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> + if (currentFile.isNotManagedByRealm()) { + currentFile.isOffline = true + currentFile.currentProgress = 0 + } + } + } else Utils.downloadAsOfflineFile(requireContext(), file) + } } } diff --git a/app/src/main/res/navigation/main_navigation.xml b/app/src/main/res/navigation/main_navigation.xml index 7280995b34..783cd40f5e 100644 --- a/app/src/main/res/navigation/main_navigation.xml +++ b/app/src/main/res/navigation/main_navigation.xml @@ -202,6 +202,14 @@ android:name="onlyFolders" android:defaultValue="false" app:argType="boolean" /> + + Date: Wed, 9 Feb 2022 16:34:06 +0100 Subject: [PATCH 002/102] Enhance favorite multi selection --- .../drive/data/models/BulkOperationType.kt | 3 ++- .../ActionMultiSelectBottomSheetDialog.kt | 16 ++++++++++++++-- .../drive/ui/fileList/FileListFragment.kt | 6 ++++++ ...fragment_bottom_sheet_action_multi_select.xml | 1 + app/src/main/res/values-de/strings.xml | 6 +++++- app/src/main/res/values-es/strings.xml | 6 +++++- app/src/main/res/values-fr/strings.xml | 6 +++++- app/src/main/res/values-it/strings.xml | 6 +++++- app/src/main/res/values/strings.xml | 6 +++++- 9 files changed, 48 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt b/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt index b63962c89b..a49552e562 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt @@ -36,7 +36,8 @@ enum class BulkOperationType(@StringRes val title: Int, @PluralsRes val successM COLOR_FOLDER(0, R.plurals.fileListColorFolderConfirmationSnackbar), SET_OFFLINE(0, successMessage = R.plurals.fileListAddOfflineConfirmationSnackbar), - ADD_FAVORITES(0, successMessage = R.plurals.fileListAddFavorisConfirmationSnackbar); + ADD_FAVORITES(0, successMessage = R.plurals.fileListAddFavoritesConfirmationSnackbar), + REMOVE_FAVORITES(0, successMessage = R.plurals.fileListRemoveFavoritesConfirmationSnackbar); fun getNotificationBuilder(context: Context): NotificationCompat.Builder { return when (this) { diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 0b3ffd37ef..cd08995c59 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -37,6 +37,7 @@ import com.infomaniak.drive.data.cache.FileController import com.infomaniak.drive.data.models.BulkOperationType import com.infomaniak.drive.utils.* import kotlinx.android.synthetic.main.fragment_bottom_sheet_action_multi_select.* +import kotlinx.android.synthetic.main.view_file_info_actions.view.* import kotlinx.coroutines.Dispatchers class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { @@ -67,9 +68,19 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun configureAddFavorites(otherActionsVisibility: Boolean) { addFavorites.apply { - setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) } + with(navigationArgs) { + addFavoritesIcon.isEnabled = onlyFavorite + if (onlyFavorite) { + addFavoritesText.setText(R.string.buttonRemoveFavorites) + setOnClickListener { onActionSelected(SelectDialogAction.REMOVE_FAVORITE) } + } else { + addFavoritesText.setText(R.string.buttonAddFavorites) + setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) } + } + } isVisible = otherActionsVisibility } + } private fun configureAvailableOffline(otherActionsVisibility: Boolean) { @@ -122,6 +133,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun onActionSelected(type: SelectDialogAction? = null) { val finalType = when (type) { SelectDialogAction.ADD_FAVORITES -> BulkOperationType.ADD_FAVORITES + SelectDialogAction.REMOVE_FAVORITE -> BulkOperationType.REMOVE_FAVORITES SelectDialogAction.OFFLINE -> BulkOperationType.SET_OFFLINE SelectDialogAction.DUPLICATE -> BulkOperationType.COPY SelectDialogAction.COLOR_FOLDER -> BulkOperationType.COLOR_FOLDER @@ -142,7 +154,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } enum class SelectDialogAction { - ADD_FAVORITES, OFFLINE, DUPLICATE, COLOR_FOLDER + ADD_FAVORITES, REMOVE_FAVORITE, OFFLINE, DUPLICATE, COLOR_FOLDER } companion object { diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 02fc12473e..6109613e61 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -450,6 +450,12 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { mainViewModel.updateMultiSelectMediator(mediator), ) } + BulkOperationType.REMOVE_FAVORITES -> { + mediator.addSource( + mainViewModel.deleteFileFromFavorites(file), + mainViewModel.updateMultiSelectMediator(mediator), + ) + } } } diff --git a/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml b/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml index 07d7929149..7e7051d092 100644 --- a/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml +++ b/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml @@ -74,6 +74,7 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/marginStandard" android:src="@drawable/ic_star_filled" + app:tint="@color/star_favorites" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 582977b482..6287141598 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -363,10 +363,14 @@ Derzeit kein Kommentar Bezeichnung der Kopie Link in Zwischenablage kopiert - + Datei erfolgreich zu Favoriten hinzugefügt %d Dateien erfolgreich zu Favoriten hinzugefügt + + Datei erfolgreich aus den Favoriten entfernt + %d Dateien erfolgreich aus den Favoriten entfernt + Datei offline verfügbar %d Dateien offline verfügbar diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c71fb0c6bf..28d0a475f2 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -363,10 +363,14 @@ Todavía no hay comentarios Nombre de la copia Enlace copiado en el portapapeles - + Un archivo añadido a favoritos correctamente %d archivos añadidos a favoritos correctamente + + Un archivo ha sido eliminado de favoritos correctamente + %d archivos han sido eliminados de favoritos correctamente + Un archivo disponible sin conexión %d archivos disponibles sin conexión diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6d7cd3ad9f..b1bd923a42 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -363,10 +363,14 @@ Aucun commentaire pour le moment Nom de la copie Lien copié dans le presse-papiers - + Un fichier ajouté aux favoris avec succès %d fichiers ajoutés aux favoris avec succès + + Un fichier retiré des favoris avec succès + %d fichiers retiré des favoris avec succès + Un fichier disponible hors ligne %d fichiers disponibles hors ligne diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3ccd5bc167..14b1b128da 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -363,10 +363,14 @@ Al momento non ci sono commenti Nome della copia Link copiato negli Appunti - + File aggiunto ai preferiti con successo %d file aggiunti ai preferiti con successo + + File rimosso ai preferiti con successo + %d file rimosso ai preferiti con successo + Un file è disponibile offline %d file sono disponibili offline diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 718a2f00bd..fc358f752b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -375,10 +375,14 @@ No comments at this time Copy name Link copied to the clipboard - + One file successfully added to favorites %d files successfully added to favorites + + One file successfully removed from favorites + %d files successfully removed from favorites + One file available offline %d files available offline From c3fd0e5102e57efa9666cf3932656d92a7095bb9 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Thu, 10 Feb 2022 08:34:07 +0100 Subject: [PATCH 003/102] refactor configureAddFavorite --- .../ActionMultiSelectBottomSheetDialog.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index cd08995c59..52b86106a9 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -68,19 +68,16 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun configureAddFavorites(otherActionsVisibility: Boolean) { addFavorites.apply { - with(navigationArgs) { - addFavoritesIcon.isEnabled = onlyFavorite - if (onlyFavorite) { - addFavoritesText.setText(R.string.buttonRemoveFavorites) - setOnClickListener { onActionSelected(SelectDialogAction.REMOVE_FAVORITE) } - } else { - addFavoritesText.setText(R.string.buttonAddFavorites) - setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) } - } + addFavoritesIcon.isEnabled = navigationArgs.onlyFavorite + if (navigationArgs.onlyFavorite) { + addFavoritesText.setText(R.string.buttonRemoveFavorites) + setOnClickListener { onActionSelected(SelectDialogAction.REMOVE_FAVORITE) } + } else { + addFavoritesText.setText(R.string.buttonAddFavorites) + setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) } } isVisible = otherActionsVisibility } - } private fun configureAvailableOffline(otherActionsVisibility: Boolean) { From 0ff0e0950876c4b98af1e9d518da2624e757c5c0 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Thu, 10 Feb 2022 10:26:36 +0100 Subject: [PATCH 004/102] Fix offline behaviour to be consistant with favorite --- .../drive/data/models/BulkOperationType.kt | 3 ++- .../ActionMultiSelectBottomSheetDialog.kt | 27 ++++++++++++------- .../drive/ui/fileList/FileListFragment.kt | 22 +++++++-------- app/src/main/res/values-de/strings.xml | 4 +++ app/src/main/res/values-es/strings.xml | 4 +++ app/src/main/res/values-fr/strings.xml | 4 +++ app/src/main/res/values-it/strings.xml | 4 +++ app/src/main/res/values/strings.xml | 4 +++ 8 files changed, 50 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt b/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt index a49552e562..87056a3fe1 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/BulkOperationType.kt @@ -35,7 +35,8 @@ enum class BulkOperationType(@StringRes val title: Int, @PluralsRes val successM COPY(R.string.fileListCopyInProgressSnackbar, R.plurals.fileListDuplicationConfirmationSnackbar), COLOR_FOLDER(0, R.plurals.fileListColorFolderConfirmationSnackbar), - SET_OFFLINE(0, successMessage = R.plurals.fileListAddOfflineConfirmationSnackbar), + ADD_OFFLINE(0, successMessage = R.plurals.fileListAddOfflineConfirmationSnackbar), + REMOVE_OFFLINE(0, successMessage = R.plurals.fileListRemoveOfflineConfirmationSnackbar), ADD_FAVORITES(0, successMessage = R.plurals.fileListAddFavoritesConfirmationSnackbar), REMOVE_FAVORITES(0, successMessage = R.plurals.fileListRemoveFavoritesConfirmationSnackbar); diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 52b86106a9..9f77793712 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -81,17 +81,23 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } private fun configureAvailableOffline(otherActionsVisibility: Boolean) { - availableOfflineSwitch.apply { - isChecked = navigationArgs.onlyOffline - setOnCheckedChangeListener { _, _ -> onActionSelected(SelectDialogAction.OFFLINE) } - } - disabledAvailableOffline.isVisible = navigationArgs.onlyFolders - availableOffline.apply { - setOnClickListener { onActionSelected(SelectDialogAction.OFFLINE) } - isVisible = otherActionsVisibility + with(navigationArgs) { + availableOfflineSwitch.apply { + isChecked = onlyOffline + setOnCheckedChangeListener { _, _ -> selectOfflineDialogActionCallBack(onlyOffline) } + } + disabledAvailableOffline.isVisible = onlyFolders + availableOffline.apply { + setOnClickListener { selectOfflineDialogActionCallBack(onlyOffline) } + isVisible = otherActionsVisibility + } } } + private fun selectOfflineDialogActionCallBack(onlyOffline: Boolean) { + onActionSelected(if (onlyOffline) SelectDialogAction.REMOVE_OFFLINE else SelectDialogAction.ADD_OFFLINE) + } + private fun configureDownloadFile() { val drivePermissions = DrivePermissions() drivePermissions.registerPermissions(this) { authorized -> if (authorized) downloadFileArchive() } @@ -131,7 +137,8 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { val finalType = when (type) { SelectDialogAction.ADD_FAVORITES -> BulkOperationType.ADD_FAVORITES SelectDialogAction.REMOVE_FAVORITE -> BulkOperationType.REMOVE_FAVORITES - SelectDialogAction.OFFLINE -> BulkOperationType.SET_OFFLINE + SelectDialogAction.ADD_OFFLINE -> BulkOperationType.ADD_OFFLINE + SelectDialogAction.REMOVE_OFFLINE -> BulkOperationType.REMOVE_OFFLINE SelectDialogAction.DUPLICATE -> BulkOperationType.COPY SelectDialogAction.COLOR_FOLDER -> BulkOperationType.COLOR_FOLDER else -> null @@ -151,7 +158,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } enum class SelectDialogAction { - ADD_FAVORITES, REMOVE_FAVORITE, OFFLINE, DUPLICATE, COLOR_FOLDER + ADD_FAVORITES, REMOVE_FAVORITE, ADD_OFFLINE, REMOVE_OFFLINE, DUPLICATE, COLOR_FOLDER } companion object { diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 6109613e61..88ee74c99f 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -434,8 +434,8 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } } - BulkOperationType.SET_OFFLINE -> { - addSelectedFilesToOffline(file) + BulkOperationType.ADD_OFFLINE, BulkOperationType.REMOVE_OFFLINE -> { + addOrRemoveSelectedFilesToOffline(file, type == BulkOperationType.ADD_OFFLINE) closeMultiSelect() } BulkOperationType.ADD_FAVORITES -> { @@ -660,18 +660,11 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } - private fun addSelectedFilesToOffline(file: File) { + private fun addOrRemoveSelectedFilesToOffline(file: File, mustAdd: Boolean) { if (!file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) - if (file.isOffline) { - lifecycleScope.launch { - if (offlineFile != null) { - mainViewModel.removeOfflineFile(file, offlineFile, cacheFile) - file.isOffline = false - } - } - } else { + if (mustAdd) { if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } @@ -683,6 +676,13 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } } else Utils.downloadAsOfflineFile(requireContext(), file) + } else { + lifecycleScope.launch { + if (offlineFile != null) { + mainViewModel.removeOfflineFile(file, offlineFile, cacheFile) + file.isOffline = false + } + } } } } diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6287141598..03c97a3823 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -375,6 +375,10 @@ Datei offline verfügbar %d Dateien offline verfügbar + + Datei aus der offline Verfügbarkeit entfernt + %d Dateien aus der offline Verfügbarkeit entfernt + Ordner erfolgreich eingefärbt %d Ordner erfolgreich eingefärbt diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 28d0a475f2..e0646a0f80 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -375,6 +375,10 @@ Un archivo disponible sin conexión %d archivos disponibles sin conexión + + Un archivo eliminado de la disponibilidad sin conexión + %d archivos eliminados de la disponibilidad sin conexión + Una carpeta coloreada con éxito %d carpetas coloreadas con éxito diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index b1bd923a42..81ffb69734 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -375,6 +375,10 @@ Un fichier disponible hors ligne %d fichiers disponibles hors ligne + + Un fichier retiré de la disponibilité hors ligne + %d fichiers retirés de la disponibilité hors ligne + Un dossier coloré avec succès %d dossiers colorés avec succès diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 14b1b128da..3228efc34f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -375,6 +375,10 @@ Un file è disponibile offline %d file sono disponibili offline + + Un file rimosso dalla disponibilità offline + %d file rimossi dalla disponibilità offline + Una cartella colorata con successo %d cartelle colorate con successo diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc358f752b..31711231b1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -387,6 +387,10 @@ One file available offline %d files available offline + + One file removed from offline availability + %d files removed from offline availability + One folder coloured successfully %d folders coloured successfully From 653daea167e713cc0e9f76952e92bd62f292690b Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Thu, 10 Feb 2022 11:16:58 +0100 Subject: [PATCH 005/102] fix sonarCloud smell --- .../drive/ui/fileList/FileListFragment.kt | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 88ee74c99f..0341e079a9 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -436,7 +436,6 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } BulkOperationType.ADD_OFFLINE, BulkOperationType.REMOVE_OFFLINE -> { addOrRemoveSelectedFilesToOffline(file, type == BulkOperationType.ADD_OFFLINE) - closeMultiSelect() } BulkOperationType.ADD_FAVORITES -> { mediator.addSource( @@ -665,25 +664,34 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) if (mustAdd) { - if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { - Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) - runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } - - fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> - if (currentFile.isNotManagedByRealm()) { - currentFile.isOffline = true - currentFile.currentProgress = 0 - } - } - } else Utils.downloadAsOfflineFile(requireContext(), file) + addSelectedFileToOffline(file, offlineFile, cacheFile) } else { - lifecycleScope.launch { - if (offlineFile != null) { - mainViewModel.removeOfflineFile(file, offlineFile, cacheFile) - file.isOffline = false - } + removeSelectedFileFromOffline(file, offlineFile, cacheFile) + } + closeMultiSelect() + } + } + + private fun addSelectedFileToOffline(file: File, offlineFile: java.io.File?, cacheFile: java.io.File) { + if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { + Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) + runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } + + fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> + if (currentFile.isNotManagedByRealm()) { + currentFile.isOffline = true + currentFile.currentProgress = 0 } } + } else Utils.downloadAsOfflineFile(requireContext(), file) + } + + private fun removeSelectedFileFromOffline(file: File, offlineFile: java.io.File?, cacheFile: java.io.File) { + lifecycleScope.launch { + if (offlineFile != null) { + mainViewModel.removeOfflineFile(file, offlineFile, cacheFile) + file.isOffline = false + } } } From 85d57e0a436e23a42a9f704af81ed6664725ac82 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 14 Feb 2022 09:19:13 +0100 Subject: [PATCH 006/102] Updated strings via Loco Signed-off-by: Kevin Boulongne --- app/src/main/res/values-de/strings.xml | 16 ++++++++-------- app/src/main/res/values-es/strings.xml | 16 ++++++++-------- app/src/main/res/values-fr/strings.xml | 16 ++++++++-------- app/src/main/res/values-it/strings.xml | 16 ++++++++-------- app/src/main/res/values/strings.xml | 16 ++++++++-------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 03c97a3823..f3da4cd40d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -367,18 +367,10 @@ Datei erfolgreich zu Favoriten hinzugefügt %d Dateien erfolgreich zu Favoriten hinzugefügt - - Datei erfolgreich aus den Favoriten entfernt - %d Dateien erfolgreich aus den Favoriten entfernt - Datei offline verfügbar %d Dateien offline verfügbar - - Datei aus der offline Verfügbarkeit entfernt - %d Dateien aus der offline Verfügbarkeit entfernt - Ordner erfolgreich eingefärbt %d Ordner erfolgreich eingefärbt @@ -404,6 +396,14 @@ %d ausgewählt %d ausgewählt + + Datei erfolgreich aus den Favoriten entfernt + %d Dateien erfolgreich aus den Favoriten entfernt + + + Datei aus der offline Verfügbarkeit entfernt + %d Dateien aus der offline Verfügbarkeit entfernt + Dateien Recht auswählen Nachricht an Gäste hinzufügen (fakultativ) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e0646a0f80..8b3bc258ef 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -367,18 +367,10 @@ Un archivo añadido a favoritos correctamente %d archivos añadidos a favoritos correctamente - - Un archivo ha sido eliminado de favoritos correctamente - %d archivos han sido eliminados de favoritos correctamente - Un archivo disponible sin conexión %d archivos disponibles sin conexión - - Un archivo eliminado de la disponibilidad sin conexión - %d archivos eliminados de la disponibilidad sin conexión - Una carpeta coloreada con éxito %d carpetas coloreadas con éxito @@ -404,6 +396,14 @@ %d seleccionado %d seleccionados + + Un archivo ha sido eliminado de favoritos correctamente + %d archivos han sido eliminados de favoritos correctamente + + + Un archivo eliminado de la disponibilidad sin conexión + %d archivos eliminados de la disponibilidad sin conexión + Archivos Seleccionar el derecho Añadir un mensaje para los invitados (opcional) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 81ffb69734..eb05a19a7a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -367,18 +367,10 @@ Un fichier ajouté aux favoris avec succès %d fichiers ajoutés aux favoris avec succès - - Un fichier retiré des favoris avec succès - %d fichiers retiré des favoris avec succès - Un fichier disponible hors ligne %d fichiers disponibles hors ligne - - Un fichier retiré de la disponibilité hors ligne - %d fichiers retirés de la disponibilité hors ligne - Un dossier coloré avec succès %d dossiers colorés avec succès @@ -404,6 +396,14 @@ %d sélectionné %d sélectionnés + + Un fichier retiré des favoris avec succès + %d fichiers retirés des favoris avec succès + + + Un fichier retiré de la disponibilité hors ligne + %d fichiers retirés de la disponibilité hors ligne + Fichiers Sélectionner le droit Ajouter un message aux invités (facultatif) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3228efc34f..11e2644133 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -367,18 +367,10 @@ File aggiunto ai preferiti con successo %d file aggiunti ai preferiti con successo - - File rimosso ai preferiti con successo - %d file rimosso ai preferiti con successo - Un file è disponibile offline %d file sono disponibili offline - - Un file rimosso dalla disponibilità offline - %d file rimossi dalla disponibilità offline - Una cartella colorata con successo %d cartelle colorate con successo @@ -404,6 +396,14 @@ %d selezionato %d selezionati + + File rimosso ai preferiti con successo + %d file rimosso ai preferiti con successo + + + Un file rimosso dalla disponibilità offline + %d file rimossi dalla disponibilità offline + File Seleziona il diritto Aggiungi un messaggio agli invitati (facoltativo) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 31711231b1..e2644b3cc2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -379,18 +379,10 @@ One file successfully added to favorites %d files successfully added to favorites - - One file successfully removed from favorites - %d files successfully removed from favorites - One file available offline %d files available offline - - One file removed from offline availability - %d files removed from offline availability - One folder coloured successfully %d folders coloured successfully @@ -416,6 +408,14 @@ %d selected %d selected + + One file successfully removed from favorites + %d files successfully removed from favorites + + + One file removed from offline availability + %d files removed from offline availability + Files Select the right Add a message for guests (optional) From 7f6e133d6ada194fc0a7efd50f0168b7dd3e048c Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 14 Feb 2022 13:54:10 +0100 Subject: [PATCH 007/102] requested changes --- .../ActionMultiSelectBottomSheetDialog.kt | 30 +++++++++---------- .../drive/ui/fileList/FileListFragment.kt | 12 +++++--- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 9f77793712..81af456630 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -69,28 +69,26 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun configureAddFavorites(otherActionsVisibility: Boolean) { addFavorites.apply { addFavoritesIcon.isEnabled = navigationArgs.onlyFavorite - if (navigationArgs.onlyFavorite) { - addFavoritesText.setText(R.string.buttonRemoveFavorites) - setOnClickListener { onActionSelected(SelectDialogAction.REMOVE_FAVORITE) } + val (text, action) = if (navigationArgs.onlyFavorite) { + R.string.buttonRemoveFavorites to SelectDialogAction.REMOVE_FAVORITE } else { - addFavoritesText.setText(R.string.buttonAddFavorites) - setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) } + R.string.buttonAddFavorites to SelectDialogAction.ADD_FAVORITES } + addFavoritesText.setText(text) + setOnClickListener { onActionSelected(action) } isVisible = otherActionsVisibility } } - private fun configureAvailableOffline(otherActionsVisibility: Boolean) { - with(navigationArgs) { - availableOfflineSwitch.apply { - isChecked = onlyOffline - setOnCheckedChangeListener { _, _ -> selectOfflineDialogActionCallBack(onlyOffline) } - } - disabledAvailableOffline.isVisible = onlyFolders - availableOffline.apply { - setOnClickListener { selectOfflineDialogActionCallBack(onlyOffline) } - isVisible = otherActionsVisibility - } + private fun configureAvailableOffline(otherActionsVisibility: Boolean) = with(navigationArgs) { + availableOfflineSwitch.apply { + isChecked = onlyOffline + setOnCheckedChangeListener { _, _ -> selectOfflineDialogActionCallBack(onlyOffline) } + } + disabledAvailableOffline.isVisible = onlyFolders + availableOffline.apply { + setOnClickListener { selectOfflineDialogActionCallBack(onlyOffline) } + isVisible = otherActionsVisibility } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 0341e079a9..dfb844c45a 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -678,12 +678,16 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> - if (currentFile.isNotManagedByRealm()) { - currentFile.isOffline = true - currentFile.currentProgress = 0 + currentFile.apply { + if (isNotManagedByRealm()) { + isOffline = true + currentProgress = 0 + } } } - } else Utils.downloadAsOfflineFile(requireContext(), file) + } else { + Utils.downloadAsOfflineFile(requireContext(), file) + } } private fun removeSelectedFileFromOffline(file: File, offlineFile: java.io.File?, cacheFile: java.io.File) { From 78f9d3d60232b4ee1dc1fe1a2c9a296018c993a2 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 14 Feb 2022 17:05:59 +0100 Subject: [PATCH 008/102] fix missing parenthesis --- .../drive/ui/fileList/FileListFragment.kt | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index dfb844c45a..9f9c6d14a0 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -484,8 +484,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { fileIds = fileAdapter.getValidItemsSelected().map { it.id }.toIntArray(), onlyFolders = fileAdapter.getValidItemsSelected().all { it.isFolder() }, ) - } - + ) } selectAllButton.apply { @@ -663,30 +662,22 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { if (!file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) - if (mustAdd) { - addSelectedFileToOffline(file, offlineFile, cacheFile) - } else { - removeSelectedFileFromOffline(file, offlineFile, cacheFile) - } - closeMultiSelect() - } - } - private fun addSelectedFileToOffline(file: File, offlineFile: java.io.File?, cacheFile: java.io.File) { - if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { - Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) - runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } + if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { + Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) + runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } - fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> - currentFile.apply { - if (isNotManagedByRealm()) { - isOffline = true - currentProgress = 0 + fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> + currentFile.apply { + if (isNotManagedByRealm()) { + isOffline = true + currentProgress = 0 + } } } + } else { + Utils.downloadAsOfflineFile(requireContext(), file) } - } else { - Utils.downloadAsOfflineFile(requireContext(), file) } } From 951a74991b74ba11801b035495fb6125bcc5abf9 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 15 Feb 2022 09:35:45 +0100 Subject: [PATCH 009/102] fix bad rebase --- .../com/infomaniak/drive/ui/MainViewModel.kt | 1 - .../ActionMultiSelectBottomSheetDialog.kt | 9 ++-- .../drive/ui/fileList/FileListFragment.kt | 44 ++++++++++++------- ...gment_bottom_sheet_action_multi_select.xml | 2 +- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt b/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt index 6985bf5d22..307dfb1402 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt @@ -42,7 +42,6 @@ import com.infomaniak.lib.core.networking.HttpClient import io.realm.Realm import io.sentry.Sentry import kotlinx.coroutines.* -import java.util.* class MainViewModel(appContext: Application) : AndroidViewModel(appContext) { diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 81af456630..020b14571a 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -83,17 +83,18 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun configureAvailableOffline(otherActionsVisibility: Boolean) = with(navigationArgs) { availableOfflineSwitch.apply { isChecked = onlyOffline - setOnCheckedChangeListener { _, _ -> selectOfflineDialogActionCallBack(onlyOffline) } + setOnCheckedChangeListener { _, _ -> selectOfflineDialogActionCallBack() } } disabledAvailableOffline.isVisible = onlyFolders availableOffline.apply { - setOnClickListener { selectOfflineDialogActionCallBack(onlyOffline) } + setOnClickListener { selectOfflineDialogActionCallBack() } isVisible = otherActionsVisibility } } - private fun selectOfflineDialogActionCallBack(onlyOffline: Boolean) { - onActionSelected(if (onlyOffline) SelectDialogAction.REMOVE_OFFLINE else SelectDialogAction.ADD_OFFLINE) + private fun selectOfflineDialogActionCallBack() { + val action = if (navigationArgs.onlyOffline) SelectDialogAction.REMOVE_OFFLINE else SelectDialogAction.ADD_OFFLINE + onActionSelected(action) } private fun configureDownloadFile() { diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 9f9c6d14a0..03a65d8789 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -479,12 +479,16 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { moveButtonMultiSelect.setOnClickListener { Utils.moveFileClicked(this, folderId) } menuButtonMultiSelect.setOnClickListener { - safeNavigate( - FileListFragmentDirections.actionFileListFragmentToActionMultiSelectBottomSheetDialog( - fileIds = fileAdapter.getValidItemsSelected().map { it.id }.toIntArray(), - onlyFolders = fileAdapter.getValidItemsSelected().all { it.isFolder() }, + with(fileAdapter.getValidItemsSelected()) { + safeNavigate( + FileListFragmentDirections.actionFileListFragmentToActionMultiSelectBottomSheetDialog( + fileIds = this.map { it.id }.toIntArray(), + onlyFolders = this.all { it.isFolder() }, + onlyFavorite = this.all { it.isFavorite }, + onlyOffline = this.all { it.isOffline }, + ) ) - ) + } } selectAllButton.apply { @@ -662,22 +666,30 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { if (!file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) + if (mustAdd) { + addSelectedFileToOffline(file, offlineFile, cacheFile) + } else { + removeSelectedFileFromOffline(file, offlineFile, cacheFile) + } + closeMultiSelect() + } + } - if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { - Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) - runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } + private fun addSelectedFileToOffline(file: File, offlineFile: java.io.File?, cacheFile: java.io.File) { + if (offlineFile != null && !file.isObsoleteOrNotIntact(cacheFile)) { + Utils.moveCacheFileToOffline(file, cacheFile, offlineFile) + runBlocking(Dispatchers.IO) { FileController.updateOfflineStatus(file.id, true) } - fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> - currentFile.apply { - if (isNotManagedByRealm()) { - isOffline = true - currentProgress = 0 - } + fileAdapter.updateFileProgressByFileId(file.id, 100) { _, currentFile -> + currentFile.apply { + if (isNotManagedByRealm()) { + isOffline = true + currentProgress = 0 } } - } else { - Utils.downloadAsOfflineFile(requireContext(), file) } + } else { + Utils.downloadAsOfflineFile(requireContext(), file) } } diff --git a/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml b/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml index 7e7051d092..0ad7e658fa 100644 --- a/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml +++ b/app/src/main/res/layout/fragment_bottom_sheet_action_multi_select.xml @@ -74,10 +74,10 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/marginStandard" android:src="@drawable/ic_star_filled" - app:tint="@color/star_favorites" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" + app:tint="@color/star_favorites" tools:ignore="ContentDescription" /> Date: Tue, 15 Feb 2022 11:12:09 +0100 Subject: [PATCH 010/102] refactor with navargs --- .../ActionMultiSelectBottomSheetDialog.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index 020b14571a..bc6835d0bc 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -66,10 +66,10 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } } - private fun configureAddFavorites(otherActionsVisibility: Boolean) { + private fun configureAddFavorites(otherActionsVisibility: Boolean) = with(navigationArgs) { addFavorites.apply { - addFavoritesIcon.isEnabled = navigationArgs.onlyFavorite - val (text, action) = if (navigationArgs.onlyFavorite) { + addFavoritesIcon.isEnabled = onlyFavorite + val (text, action) = if (onlyFavorite) { R.string.buttonRemoveFavorites to SelectDialogAction.REMOVE_FAVORITE } else { R.string.buttonAddFavorites to SelectDialogAction.ADD_FAVORITES From e45ca445c734c6329c6ab44302e4949742edb4d5 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Tue, 15 Feb 2022 14:00:42 +0100 Subject: [PATCH 011/102] Fixed rights when creating a Common folder Signed-off-by: Kevin Boulongne --- .../main/java/com/infomaniak/drive/data/api/ApiRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/api/ApiRepository.kt b/app/src/main/java/com/infomaniak/drive/data/api/ApiRepository.kt index f61317551f..dd3ffe8300 100644 --- a/app/src/main/java/com/infomaniak/drive/data/api/ApiRepository.kt +++ b/app/src/main/java/com/infomaniak/drive/data/api/ApiRepository.kt @@ -139,7 +139,7 @@ object ApiRepository { return callApi( ApiRoutes.createTeamFolder(driveId), POST, - mapOf("name" to name, "for_all_users" to forAllUsers), + mapOf("name" to name, "for_all_user" to forAllUsers), okHttpClient = okHttpClient ) } From 5a0a87bbbca1ae0574d77ba95453442c8a96081a Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 7 Feb 2022 14:07:48 +0100 Subject: [PATCH 012/102] Removed StartActivityForResult in SaveExternalFilesActivity Signed-off-by: Kevin Boulongne --- .../drive/ui/SaveExternalFilesActivity.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt index 7ab4af7eae..daf6951d8f 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.drive.ui +import android.app.Activity import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color @@ -24,6 +25,7 @@ import android.net.Uri import android.os.Bundle import android.os.Parcelable import android.provider.OpenableColumns +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.core.net.toUri @@ -100,7 +102,7 @@ class SaveExternalFilesActivity : BaseActivity() { putExtra(SelectFolderActivity.USER_ID_TAG, selectDriveViewModel.selectedUserId.value) putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, selectDriveViewModel.selectedDrive.value?.id) } - startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + selectFolderResultLauncher.launch(intent) } } ?: run { showSelectDrive() @@ -156,6 +158,15 @@ class SaveExternalFilesActivity : BaseActivity() { } } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + saveExternalFilesViewModel.folderId.value = folderId + } + } + } + override fun onResume() { super.onResume() if (drivePermissions.checkWriteStoragePermission(false)) getFiles() @@ -180,14 +191,6 @@ class SaveExternalFilesActivity : BaseActivity() { } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == SelectFolderActivity.SELECT_FOLDER_REQUEST && resultCode == RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - saveExternalFilesViewModel.folderId.value = folderId - } - } - private fun activeDefaultUser() { AccountUtils.getAllUsers().observe(this) { users -> if (users.size > 1) activeSelectDrive() From 8f21653362872b9b633dc41214f8ae4a5c84e59e Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 7 Feb 2022 14:20:49 +0100 Subject: [PATCH 013/102] Removed StartActivityForResult in TrashedFileActionsBottomSheetDialog Signed-off-by: Kevin Boulongne --- .../TrashedFileActionsBottomSheetDialog.kt | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt index 88207106f1..dc35c1eb7e 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt @@ -17,12 +17,13 @@ */ package com.infomaniak.drive.ui.bottomSheetDialogs +import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels import com.google.android.material.bottomsheet.BottomSheetDialogFragment @@ -59,7 +60,7 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { putExtra(SelectFolderActivity.USER_ID_TAG, AccountUtils.currentUserId) putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, AccountUtils.currentDriveId) } - startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + selectFolderResultLauncher.launch(intent) } restoreFileToOriginalPlace.setOnClickListener { @@ -85,17 +86,18 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == SelectFolderActivity.SELECT_FOLDER_REQUEST && resultCode == AppCompatActivity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) - folderId?.let { - trashViewModel.restoreTrashFile( - currentTrashedFile, - File(id = folderId, name = folderName.toString()) - ).observe(this) { apiResponse -> - restoreResult(apiResponse, originalPlace = false, folderName = folderName) + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) + folderId?.let { + trashViewModel.restoreTrashFile( + currentTrashedFile, + File(id = folderId, name = folderName.toString()), + ).observe(this@TrashedFileActionsBottomSheetDialog) { apiResponse -> + restoreResult(apiResponse, originalPlace = false, folderName = folderName) + } } } } From 5d6657def1f0d334c1687c4fe6e983108ef5c29d Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 7 Feb 2022 14:21:50 +0100 Subject: [PATCH 014/102] Removed StartActivityForResult in SyncSettingsActivity Signed-off-by: Kevin Boulongne --- .../drive/ui/menu/settings/SyncSettingsActivity.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt index ea0e1f586f..0b9330f9ac 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt @@ -17,10 +17,12 @@ */ package com.infomaniak.drive.ui.menu.settings +import android.app.Activity import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.core.view.isGone @@ -141,7 +143,7 @@ class SyncSettingsActivity : BaseActivity() { putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, selectDriveViewModel.selectedDrive.value?.id) putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, Utils.ROOT_ID) } - startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + selectFolderResultLauncher.launch(intent) } syncSettingsViewModel.syncFolder.observe(this) { syncFolder -> @@ -224,10 +226,12 @@ class SyncSettingsActivity : BaseActivity() { } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == SelectFolderActivity.SELECT_FOLDER_REQUEST && resultCode == RESULT_OK) { - syncSettingsViewModel.syncFolder.value = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + syncSettingsViewModel.syncFolder.value = folderId + } } } From ac9b5df70f79e47c9412cbc485bf5f64a0629566 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Tue, 8 Feb 2022 15:22:01 +0100 Subject: [PATCH 015/102] Removed OnActivityResult in LoginActivity Signed-off-by: Kevin Boulongne --- .../drive/ui/login/LoginActivity.kt | 31 +++++++++---------- .../java/com/infomaniak/drive/utils/Utils.kt | 2 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt index 16732efedc..4e587fa12a 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt @@ -20,6 +20,7 @@ package com.infomaniak.drive.ui.login import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isInvisible @@ -84,29 +85,27 @@ class LoginActivity : AppCompatActivity() { setOnClickListener { signInButton.isEnabled = false showProgress() - infomaniakLogin.startWebViewLogin(WEB_VIEW_LOGIN_REQ) + infomaniakLogin.startWebViewLogin(webViewLoginResultLauncher) } } signInButton.setOnClickListener { openUrl(ApiRoutes.orderDrive()) } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == WEB_VIEW_LOGIN_REQ && resultCode == RESULT_OK) { - val authCode = data?.extras?.getString(InfomaniakLogin.CODE_TAG) - val translatedError = data?.extras?.getString(InfomaniakLogin.ERROR_TRANSLATED_TAG) - - if (!translatedError.isNullOrBlank()) { - showError(translatedError) - } else if (!authCode.isNullOrBlank()) { - authenticateUser(authCode) + private val webViewLoginResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == RESULT_OK) { + val authCode = data?.extras?.getString(InfomaniakLogin.CODE_TAG) + val translatedError = data?.extras?.getString(InfomaniakLogin.ERROR_TRANSLATED_TAG) + when { + translatedError?.isNotBlank() == true -> showError(translatedError) + authCode?.isNotBlank() == true -> authenticateUser(authCode) + else -> showError(getString(R.string.anErrorHasOccurred)) + } } else { - showError(getString(R.string.anErrorHasOccurred)) + connectButton?.hideProgress(R.string.connect) + signInButton.isEnabled = true } - } else { - connectButton?.hideProgress(R.string.connect) - signInButton.isEnabled = true } } @@ -160,8 +159,6 @@ class LoginActivity : AppCompatActivity() { } companion object { - private const val WEB_VIEW_LOGIN_REQ = 1 - suspend fun authenticateUser(context: Context, apiToken: ApiToken): Any { AccountUtils.getUserById(apiToken.userId)?.let { diff --git a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt index 49d944c0ca..bc4b940f21 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt @@ -224,7 +224,7 @@ object Utils { putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, currentFolder) putExtra( SelectFolderActivity.CUSTOM_ARGS_TAG, - bundleOf(SelectFolderActivity.BULK_OPERATION_CUSTOM_TAG to BulkOperationType.MOVE) + bundleOf(SelectFolderActivity.BULK_OPERATION_CUSTOM_TAG to BulkOperationType.MOVE), ) } ownerFragment.startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) From bdd0978a8f739165c3acfe4df997bc4a914e570c Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 7 Feb 2022 13:40:17 +0100 Subject: [PATCH 016/102] Removed StartActivityForResult in AddFileBottomSheetDialog Signed-off-by: Kevin Boulongne --- .../ui/addFiles/AddFileBottomSheetDialog.kt | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt index 4e2f9f9b3a..c8982f9833 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt @@ -26,6 +26,7 @@ import android.provider.MediaStore import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.content.FileProvider import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.activityViewModels @@ -63,11 +64,6 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { private var mediaPhotoPath = "" private var mediaVideoPath = "" - companion object { - const val SELECT_FILES_REQ = 2 - const val CAPTURE_MEDIA_REQ = 3 - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return (mainViewModel.currentFolderOpenAddFileBottom.value ?: mainViewModel.currentFolder.value)?.let { currentFolderFile = it @@ -106,18 +102,6 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { mainViewModel.currentFolderOpenAddFileBottom.value = null } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - - if (resultCode == Activity.RESULT_OK) { - when (requestCode) { - SELECT_FILES_REQ -> onSelectFilesResult(data) - CAPTURE_MEDIA_REQ -> onCaptureMediaResult(data) - } - } - dismiss() - } - private fun openCamera() { if (openCameraPermissions.checkSyncPermissions()) { openCamera.isEnabled = false @@ -129,15 +113,23 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { val takeVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE).apply { putExtra(MediaStore.EXTRA_OUTPUT, createMediaFile(true)) } - val chooserIntent = Intent.createChooser(takePictureIntent, getString(R.string.buttonTakePhotoOrVideo)) - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(takeVideoIntent)) - startActivityForResult(chooserIntent, CAPTURE_MEDIA_REQ) + val chooserIntent = Intent.createChooser(takePictureIntent, getString(R.string.buttonTakePhotoOrVideo)).apply { + putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(takeVideoIntent)) + } + captureMediaResultLauncher.launch(chooserIntent) } catch (e: IOException) { e.printStackTrace() } } } + private val captureMediaResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) onCaptureMediaResult(data) + } + dismiss() + } + private fun uploadFiles() { if (uploadFilesPermissions.checkSyncPermissions()) { documentUpload.isEnabled = false @@ -148,10 +140,18 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) addCategory(Intent.CATEGORY_OPENABLE) } - startActivityForResult(Intent.createChooser(intent, getString(R.string.addFileSelectUploadFile)), SELECT_FILES_REQ) + val chooserIntent = Intent.createChooser(intent, getString(R.string.addFileSelectUploadFile)) + selectFilesResultLauncher.launch(chooserIntent) } } + private val selectFilesResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) onSelectFilesResult(data) + } + dismiss() + } + private fun scanDocuments() { // TODO find a good lib dismiss() From aa21a7d5fd651b7c9684c580f6eb49888ca78b0c Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Fri, 11 Feb 2022 15:29:47 +0100 Subject: [PATCH 017/102] Removed StartActivityForResult in FileListFragment Signed-off-by: Kevin Boulongne --- .../FileInfoActionsBottomSheetDialog.kt | 14 ++++--- .../drive/ui/fileList/FileListFragment.kt | 42 +++++++++---------- .../drive/ui/fileList/SelectFolderActivity.kt | 1 - .../fileList/preview/PreviewSliderFragment.kt | 14 ++++--- .../java/com/infomaniak/drive/utils/Utils.kt | 8 ++-- .../drive/views/FileInfoActionsView.kt | 21 ++++++---- 6 files changed, 52 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt index 40039ecd0a..d762539f26 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt @@ -17,11 +17,11 @@ */ package com.infomaniak.drive.ui.bottomSheetDialogs -import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -61,6 +61,12 @@ class FileInfoActionsBottomSheetDialog : BottomSheetDialogFragment(), FileInfoAc private val mainViewModel: MainViewModel by activityViewModels() private val navigationArgs: FileInfoActionsBottomSheetDialogArgs by navArgs() + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == android.app.Activity.RESULT_OK) onSelectFolderResult(data) + } + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.fragment_bottom_sheet_file_info_actions, container, false) } @@ -82,6 +88,7 @@ class FileInfoActionsBottomSheetDialog : BottomSheetDialogFragment(), FileInfoAc ownerFragment = this@FileInfoActionsBottomSheetDialog, mainViewModel = mainViewModel, onItemClickListener = this@FileInfoActionsBottomSheetDialog, + selectFolderResultLauncher = selectFolderResultLauncher, isSharedWithMe = navigationArgs.userDrive.sharedWithMe, ) updateCurrentFile(currentFile) @@ -118,11 +125,6 @@ class FileInfoActionsBottomSheetDialog : BottomSheetDialogFragment(), FileInfoAc } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - onSelectFolderResult(requestCode, resultCode, data) - } - override fun onResume() { super.onResume() // Fix the popBackStack in onViewCreated because onResume is still called diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index c976034f56..7b578c4d42 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.drive.ui.fileList +import android.app.Activity import android.app.Dialog import android.content.Intent import android.os.Bundle @@ -26,7 +27,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.addCallback -import androidx.appcompat.app.AppCompatActivity +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.ViewCompat @@ -281,11 +282,6 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - data?.let { onSelectFolderResult(requestCode, resultCode, data) } - } - override fun onStart() { super.onStart() fileAdapter.resetRealmListener() @@ -470,7 +466,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { deleteButtonMultiSelect.setOnClickListener { performBulkOperation(BulkOperationType.TRASH) } - moveButtonMultiSelect.setOnClickListener { Utils.moveFileClicked(this, folderId) } + moveButtonMultiSelect.setOnClickListener { Utils.moveFileClicked(context, folderId, selectFolderResultLauncher) } menuButtonMultiSelect.setOnClickListener { safeNavigate( @@ -638,7 +634,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { bundleOf(BULK_OPERATION_CUSTOM_TAG to BulkOperationType.COPY), ) } - startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + selectFolderResultLauncher.launch(intent) } BulkOperationType.COLOR_FOLDER -> { if (AccountUtils.getCurrentDrive()?.pack == Drive.DrivePack.FREE.value) { @@ -652,6 +648,22 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)!! + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() + val customArgs = data?.extras?.getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) + val bulkOperationType = customArgs?.getParcelable(BULK_OPERATION_CUSTOM_TAG)!! + + performBulkOperation( + type = bulkOperationType, + destinationFolder = File(id = folderId, name = folderName, driveId = AccountUtils.currentDriveId), + ) + } + } + } + private fun addSelectedFilesToOffline(file: File) { if (!file.isOffline && !file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) @@ -671,20 +683,6 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } - private fun onSelectFolderResult(requestCode: Int, resultCode: Int, data: Intent) { - if (requestCode == SelectFolderActivity.SELECT_FOLDER_REQUEST && resultCode == AppCompatActivity.RESULT_OK) { - val folderName = data.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() - val folderId = data.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)!! - val customArgs = data.extras?.getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) - val bulkOperationType = customArgs?.getParcelable(BULK_OPERATION_CUSTOM_TAG)!! - - performBulkOperation( - type = bulkOperationType, - destinationFolder = File(id = folderId, name = folderName, driveId = AccountUtils.currentDriveId) - ) - } - } - private fun checkIfNoFiles() { changeNoFilesLayoutVisibility( hideFileList = fileAdapter.itemCount == 0, diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt index a27d60d691..fe98dc6fbc 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt @@ -38,7 +38,6 @@ class SelectFolderActivity : BaseActivity() { private val mainViewModel: MainViewModel by viewModels() companion object { - const val SELECT_FOLDER_REQUEST = 42 const val USER_ID_TAG = "userId" const val USER_DRIVE_ID_TAG = "userDriveId" const val FOLDER_ID_TAG = "folderId" diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt index c366e7cb49..954b7dcb8c 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt @@ -18,12 +18,12 @@ package com.infomaniak.drive.ui.fileList.preview import android.annotation.SuppressLint -import android.content.Intent import android.os.Bundle import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.core.content.ContextCompat import androidx.core.view.isGone import androidx.core.view.isVisible @@ -70,6 +70,12 @@ class PreviewSliderFragment : Fragment(), FileInfoActionsView.OnItemClickListene private var hideActions: Boolean = false private var showUi = false + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == android.app.Activity.RESULT_OK) onSelectFolderResult(data) + } + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { if (mainViewModel.currentPreviewFileList.isEmpty()) { @@ -114,6 +120,7 @@ class PreviewSliderFragment : Fragment(), FileInfoActionsView.OnItemClickListene ownerFragment = this@PreviewSliderFragment, mainViewModel = mainViewModel, onItemClickListener = this@PreviewSliderFragment, + selectFolderResultLauncher = selectFolderResultLauncher, isSharedWithMe = userDrive.sharedWithMe, ) updateCurrentFile(currentPreviewFile) @@ -203,11 +210,6 @@ class PreviewSliderFragment : Fragment(), FileInfoActionsView.OnItemClickListene } } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - onSelectFolderResult(requestCode, resultCode, data) - } - override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt index bc4b940f21..118cfffd71 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt @@ -26,6 +26,7 @@ import android.os.Environment import android.provider.DocumentsContract import android.view.View import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog @@ -35,7 +36,6 @@ import androidx.core.os.bundleOf import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged -import androidx.fragment.app.Fragment import androidx.navigation.NavController import androidx.navigation.NavOptions import androidx.work.* @@ -217,8 +217,8 @@ object Utils { clipboard?.setPrimaryClip(ClipData.newPlainText(text, text)) } - fun moveFileClicked(ownerFragment: Fragment, currentFolder: Int) { - val intent = Intent(ownerFragment.context, SelectFolderActivity::class.java).apply { + fun moveFileClicked(context: Context?, currentFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { + val intent = Intent(context, SelectFolderActivity::class.java).apply { putExtra(SelectFolderActivity.USER_ID_TAG, AccountUtils.currentUserId) putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, AccountUtils.currentDriveId) putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, currentFolder) @@ -227,7 +227,7 @@ object Utils { bundleOf(SelectFolderActivity.BULK_OPERATION_CUSTOM_TAG to BulkOperationType.MOVE), ) } - ownerFragment.startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + selectFolderResultLauncher.launch(intent) } fun Context.openWith(file: File, userDrive: UserDrive = UserDrive()) { diff --git a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt index ef02c015b5..3cc207a54c 100644 --- a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt +++ b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt @@ -24,7 +24,7 @@ import android.util.AttributeSet import android.util.Log import android.view.View import android.widget.FrameLayout -import androidx.appcompat.app.AppCompatActivity +import androidx.activity.result.ActivityResultLauncher import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.fragment.app.Fragment @@ -63,6 +63,7 @@ class FileInfoActionsView @JvmOverloads constructor( private lateinit var ownerFragment: Fragment private lateinit var onItemClickListener: OnItemClickListener + private lateinit var selectFolderResultLauncher: ActivityResultLauncher private var isSharedWithMe = false init { @@ -73,12 +74,14 @@ class FileInfoActionsView @JvmOverloads constructor( ownerFragment: Fragment, mainViewModel: MainViewModel, onItemClickListener: OnItemClickListener, + selectFolderResultLauncher: ActivityResultLauncher, isSharedWithMe: Boolean = false, ) { this.isSharedWithMe = isSharedWithMe this.mainViewModel = mainViewModel this.onItemClickListener = onItemClickListener this.ownerFragment = ownerFragment + this.selectFolderResultLauncher = selectFolderResultLauncher initOnClickListeners() } @@ -196,7 +199,7 @@ class FileInfoActionsView @JvmOverloads constructor( availableOffline.setOnClickListener { availableOfflineSwitch.performClick() } moveFile.setOnClickListener { val currentFolder = FileController.getParentFile(currentFile.id)?.id ?: -42 - onItemClickListener.moveFileClicked(ownerFragment, currentFolder) + onItemClickListener.moveFileClicked(ownerFragment.context, currentFolder, selectFolderResultLauncher) } duplicateFile.setOnClickListener { onItemClickListener.duplicateFileClicked(ownerFragment.requireContext(), currentFile) } renameFile.setOnClickListener { onItemClickListener.renameFileClicked(ownerFragment.requireContext(), currentFile) } @@ -405,12 +408,10 @@ class FileInfoActionsView @JvmOverloads constructor( ownerFragment.openOnlyOfficeDocument(currentFile) } - fun onSelectFolderResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == SelectFolderActivity.SELECT_FOLDER_REQUEST && resultCode == AppCompatActivity.RESULT_OK) { - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() - data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)?.let { - onMoveFile(File(id = it, name = folderName, driveId = AccountUtils.currentDriveId)) - } + fun onSelectFolderResult(data: Intent?) { + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() + data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)?.let { + onMoveFile(File(id = it, name = folderName, driveId = AccountUtils.currentDriveId)) } } @@ -427,7 +428,9 @@ class FileInfoActionsView @JvmOverloads constructor( } } - fun moveFileClicked(ownerFragment: Fragment, idFolder: Int) = Utils.moveFileClicked(ownerFragment, idFolder) + fun moveFileClicked(context: Context?, idFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { + Utils.moveFileClicked(context, idFolder, selectFolderResultLauncher) + } fun duplicateFileClicked(context: Context, currentFile: File) { currentFile.apply { From 714479c02e456698a38aba3ea43b94f3f26a60b6 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 14 Feb 2022 15:14:37 +0100 Subject: [PATCH 018/102] Moved ResultLaunchers to the top of classes Signed-off-by: Kevin Boulongne --- Core | 2 +- .../com/infomaniak/drive/ui/MainActivity.kt | 16 ++++----- .../drive/ui/SaveExternalFilesActivity.kt | 18 +++++----- .../ui/addFiles/AddFileBottomSheetDialog.kt | 28 +++++++-------- .../TrashedFileActionsBottomSheetDialog.kt | 34 +++++++++---------- .../drive/ui/fileList/FileListFragment.kt | 32 ++++++++--------- .../drive/ui/login/LoginActivity.kt | 34 +++++++++---------- .../ui/menu/settings/SyncSettingsActivity.kt | 18 +++++----- 8 files changed, 89 insertions(+), 93 deletions(-) diff --git a/Core b/Core index 9727b373e4..f1ed05aaec 160000 --- a/Core +++ b/Core @@ -1 +1 @@ -Subproject commit 9727b373e44fda05165990f227c3257b7a571cdb +Subproject commit f1ed05aaec4161dfb5da193e49f9e1ac95a6b8c3 diff --git a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt index 6709727b5e..5ded15fff9 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt @@ -35,7 +35,6 @@ import android.provider.DocumentsContract import android.provider.MediaStore import android.util.Log import android.view.View -import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.IntentSenderRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels @@ -91,7 +90,12 @@ class MainActivity : BaseActivity() { private var hasDisplayedInformationPanel: Boolean = false private lateinit var drivePermissions: DrivePermissions - private lateinit var filesDeletionResult: ActivityResultLauncher + + private val filesDeletionResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> + if (result.resultCode == RESULT_OK) { + lifecycleScope.launch(Dispatchers.IO) { UploadFile.deleteAll(uploadedFilesToDelete) } + } + } private val fileObserver: FileObserver by lazy { fun onEvent() { @@ -155,14 +159,6 @@ class MainActivity : BaseActivity() { } } - filesDeletionResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> - if (result.resultCode == RESULT_OK) { - lifecycleScope.launch(Dispatchers.IO) { - UploadFile.deleteAll(uploadedFilesToDelete) - } - } - } - LiveDataNetworkStatus(this).observe(this) { isAvailable -> Log.d("Internet availability", if (isAvailable) "Available" else "Unavailable") Sentry.addBreadcrumb(Breadcrumb().apply { diff --git a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt index daf6951d8f..e10de366bd 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt @@ -68,6 +68,15 @@ class SaveExternalFilesActivity : BaseActivity() { private var currentUri: Uri? = null private var isMultiple = false + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + saveExternalFilesViewModel.folderId.value = folderId + } + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_save_external_file) @@ -158,15 +167,6 @@ class SaveExternalFilesActivity : BaseActivity() { } } - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - saveExternalFilesViewModel.folderId.value = folderId - } - } - } - override fun onResume() { super.onResume() if (drivePermissions.checkWriteStoragePermission(false)) getFiles() diff --git a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt index c8982f9833..4139951255 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt @@ -64,6 +64,20 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { private var mediaPhotoPath = "" private var mediaVideoPath = "" + private val captureMediaResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) onCaptureMediaResult(data) + } + dismiss() + } + + private val selectFilesResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) onSelectFilesResult(data) + } + dismiss() + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return (mainViewModel.currentFolderOpenAddFileBottom.value ?: mainViewModel.currentFolder.value)?.let { currentFolderFile = it @@ -123,13 +137,6 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { } } - private val captureMediaResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) onCaptureMediaResult(data) - } - dismiss() - } - private fun uploadFiles() { if (uploadFilesPermissions.checkSyncPermissions()) { documentUpload.isEnabled = false @@ -145,13 +152,6 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { } } - private val selectFilesResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) onSelectFilesResult(data) - } - dismiss() - } - private fun scanDocuments() { // TODO find a good lib dismiss() diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt index dc35c1eb7e..f34ac12ca4 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt @@ -46,6 +46,23 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { private lateinit var currentTrashedFile: File private val trashViewModel: TrashViewModel by navGraphViewModels(R.id.trashFragment) + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) + folderId?.let { + trashViewModel.restoreTrashFile( + currentTrashedFile, + File(id = folderId, name = folderName.toString()), + ).observe(this@TrashedFileActionsBottomSheetDialog) { apiResponse -> + restoreResult(apiResponse, originalPlace = false, folderName = folderName) + } + } + } + } + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.fragment_bottom_sheet_trashed_file_actions, container, false) } @@ -86,23 +103,6 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { } } - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) - folderId?.let { - trashViewModel.restoreTrashFile( - currentTrashedFile, - File(id = folderId, name = folderName.toString()), - ).observe(this@TrashedFileActionsBottomSheetDialog) { apiResponse -> - restoreResult(apiResponse, originalPlace = false, folderName = folderName) - } - } - } - } - } - private fun restoreResult(apiResponse: ApiResponse, originalPlace: Boolean, folderName: String? = null) { if (apiResponse.isSuccess()) { val title = if (originalPlace) R.string.trashedFileRestoreFileToOriginalPlaceSuccess diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 7b578c4d42..5f25b7d24f 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -111,6 +111,22 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { protected var userDrive: UserDrive? = null + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)!! + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() + val customArgs = data?.extras?.getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) + val bulkOperationType = customArgs?.getParcelable(BULK_OPERATION_CUSTOM_TAG)!! + + performBulkOperation( + type = bulkOperationType, + destinationFolder = File(id = folderId, name = folderName, driveId = AccountUtils.currentDriveId), + ) + } + } + } + companion object { const val REFRESH_FAVORITE_FILE = "force_list_refresh" const val CANCELLABLE_MAIN_KEY = "cancellable_main" @@ -648,22 +664,6 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)!! - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() - val customArgs = data?.extras?.getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) - val bulkOperationType = customArgs?.getParcelable(BULK_OPERATION_CUSTOM_TAG)!! - - performBulkOperation( - type = bulkOperationType, - destinationFolder = File(id = folderId, name = folderName, driveId = AccountUtils.currentDriveId), - ) - } - } - } - private fun addSelectedFilesToOffline(file: File) { if (!file.isOffline && !file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) diff --git a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt index 4e587fa12a..d20847d62a 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt @@ -57,6 +57,23 @@ class LoginActivity : AppCompatActivity() { private lateinit var infomaniakLogin: InfomaniakLogin + private val webViewLoginResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == RESULT_OK) { + val authCode = data?.extras?.getString(InfomaniakLogin.CODE_TAG) + val translatedError = data?.extras?.getString(InfomaniakLogin.ERROR_TRANSLATED_TAG) + when { + translatedError?.isNotBlank() == true -> showError(translatedError) + authCode?.isNotBlank() == true -> authenticateUser(authCode) + else -> showError(getString(R.string.anErrorHasOccurred)) + } + } else { + connectButton?.hideProgress(R.string.connect) + signInButton.isEnabled = true + } + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) @@ -92,23 +109,6 @@ class LoginActivity : AppCompatActivity() { signInButton.setOnClickListener { openUrl(ApiRoutes.orderDrive()) } } - private val webViewLoginResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == RESULT_OK) { - val authCode = data?.extras?.getString(InfomaniakLogin.CODE_TAG) - val translatedError = data?.extras?.getString(InfomaniakLogin.ERROR_TRANSLATED_TAG) - when { - translatedError?.isNotBlank() == true -> showError(translatedError) - authCode?.isNotBlank() == true -> authenticateUser(authCode) - else -> showError(getString(R.string.anErrorHasOccurred)) - } - } else { - connectButton?.hideProgress(R.string.connect) - signInButton.isEnabled = true - } - } - } - private fun authenticateUser(authCode: String) { lifecycleScope.launch { infomaniakLogin.getToken( diff --git a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt index 0b9330f9ac..8f2d8f3e9f 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt @@ -67,6 +67,15 @@ class SyncSettingsActivity : BaseActivity() { private var oldSyncSettings: SyncSettings? = null private var editNumber = 0 + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> + with(result) { + if (resultCode == Activity.RESULT_OK) { + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + syncSettingsViewModel.syncFolder.value = folderId + } + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_sync_settings) @@ -226,15 +235,6 @@ class SyncSettingsActivity : BaseActivity() { } } - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - syncSettingsViewModel.syncFolder.value = folderId - } - } - } - fun onDialogDismissed() { syncSettingsVisibility(MediaFolder.getAllSyncedFoldersCount() > 0) changeSaveButtonStatus() From 88e38d4f77b4d9128eb6d682d6f562f5173d3226 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Mon, 14 Feb 2022 16:02:11 +0100 Subject: [PATCH 019/102] Moved `ActivityResult` into extension function: `whenResultIsOk` Signed-off-by: Kevin Boulongne --- .../com/infomaniak/drive/ui/MainActivity.kt | 8 ++--- .../drive/ui/SaveExternalFilesActivity.kt | 11 +++---- .../ui/addFiles/AddFileBottomSheetDialog.kt | 13 +++----- .../FileInfoActionsBottomSheetDialog.kt | 8 ++--- .../TrashedFileActionsBottomSheetDialog.kt | 32 ++++++++----------- .../drive/ui/fileList/FileListFragment.kt | 15 ++++----- .../fileList/preview/PreviewSliderFragment.kt | 6 ++-- .../drive/ui/login/LoginActivity.kt | 6 ++-- .../ui/menu/settings/SyncSettingsActivity.kt | 23 ++++--------- .../com/infomaniak/drive/utils/Extensions.kt | 6 ++++ 10 files changed, 51 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt index 5ded15fff9..2e40e7c90c 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt @@ -36,7 +36,7 @@ import android.provider.MediaStore import android.util.Log import android.view.View import androidx.activity.result.IntentSenderRequest -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toBitmap @@ -91,10 +91,8 @@ class MainActivity : BaseActivity() { private lateinit var drivePermissions: DrivePermissions - private val filesDeletionResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> - if (result.resultCode == RESULT_OK) { - lifecycleScope.launch(Dispatchers.IO) { UploadFile.deleteAll(uploadedFilesToDelete) } - } + private val filesDeletionResult = registerForActivityResult(StartIntentSenderForResult()) { + it.whenResultIsOk { lifecycleScope.launch(Dispatchers.IO) { UploadFile.deleteAll(uploadedFilesToDelete) } } } private val fileObserver: FileObserver by lazy { diff --git a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt index e10de366bd..d585fa8a80 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.drive.ui -import android.app.Activity import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color @@ -68,12 +67,10 @@ class SaveExternalFilesActivity : BaseActivity() { private var currentUri: Uri? = null private var isMultiple = false - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - saveExternalFilesViewModel.folderId.value = folderId - } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + saveExternalFilesViewModel.folderId.value = folderId } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt index 4139951255..49a8686bed 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/addFiles/AddFileBottomSheetDialog.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.drive.ui.addFiles -import android.app.Activity import android.content.DialogInterface import android.content.Intent import android.net.Uri @@ -64,17 +63,13 @@ class AddFileBottomSheetDialog : BottomSheetDialogFragment() { private var mediaPhotoPath = "" private var mediaVideoPath = "" - private val captureMediaResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) onCaptureMediaResult(data) - } + private val captureMediaResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> onCaptureMediaResult(data) } dismiss() } - private val selectFilesResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) onSelectFilesResult(data) - } + private val selectFilesResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> onSelectFilesResult(data) } dismiss() } diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt index d762539f26..12dc43887f 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/FileInfoActionsBottomSheetDialog.kt @@ -21,7 +21,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -61,10 +61,8 @@ class FileInfoActionsBottomSheetDialog : BottomSheetDialogFragment(), FileInfoAc private val mainViewModel: MainViewModel by activityViewModels() private val navigationArgs: FileInfoActionsBottomSheetDialogArgs by navArgs() - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == android.app.Activity.RESULT_OK) onSelectFolderResult(data) - } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> onSelectFolderResult(data) } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt index f34ac12ca4..124ab1eb41 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/TrashedFileActionsBottomSheetDialog.kt @@ -17,13 +17,12 @@ */ package com.infomaniak.drive.ui.bottomSheetDialogs -import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels import com.google.android.material.bottomsheet.BottomSheetDialogFragment @@ -34,10 +33,7 @@ import com.infomaniak.drive.data.api.ErrorCode.Companion.translateError import com.infomaniak.drive.data.models.File import com.infomaniak.drive.ui.fileList.SelectFolderActivity import com.infomaniak.drive.ui.menu.TrashViewModel -import com.infomaniak.drive.utils.AccountUtils -import com.infomaniak.drive.utils.Utils -import com.infomaniak.drive.utils.setFileItem -import com.infomaniak.drive.utils.showSnackbar +import com.infomaniak.drive.utils.* import com.infomaniak.lib.core.models.ApiResponse import kotlinx.android.synthetic.main.fragment_bottom_sheet_trashed_file_actions.* @@ -46,18 +42,16 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { private lateinit var currentTrashedFile: File private val trashViewModel: TrashViewModel by navGraphViewModels(R.id.trashFragment) - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) - folderId?.let { - trashViewModel.restoreTrashFile( - currentTrashedFile, - File(id = folderId, name = folderName.toString()), - ).observe(this@TrashedFileActionsBottomSheetDialog) { apiResponse -> - restoreResult(apiResponse, originalPlace = false, folderName = folderName) - } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG) + folderId?.let { + trashViewModel.restoreTrashFile( + currentTrashedFile, + File(id = folderId, name = folderName.toString()), + ).observe(this@TrashedFileActionsBottomSheetDialog) { apiResponse -> + restoreResult(apiResponse, originalPlace = false, folderName = folderName) } } } @@ -127,4 +121,4 @@ class TrashedFileActionsBottomSheetDialog : BottomSheetDialogFragment() { findNavController().popBackStack() trashViewModel.removeFileId.value = currentTrashedFile.id } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 5f25b7d24f..7a376234bd 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.drive.ui.fileList -import android.app.Activity import android.app.Dialog import android.content.Intent import android.os.Bundle @@ -27,7 +26,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.addCallback -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.ViewCompat @@ -111,12 +110,12 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { protected var userDrive: UserDrive? = null - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)!! - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() - val customArgs = data?.extras?.getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> + with(data?.extras!!) { + val folderId = getInt(SelectFolderActivity.FOLDER_ID_TAG) + val folderName = getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() + val customArgs = getBundle(SelectFolderActivity.CUSTOM_ARGS_TAG) val bulkOperationType = customArgs?.getParcelable(BULK_OPERATION_CUSTOM_TAG)!! performBulkOperation( diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt index 954b7dcb8c..17748e1221 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewSliderFragment.kt @@ -70,10 +70,8 @@ class PreviewSliderFragment : Fragment(), FileInfoActionsView.OnItemClickListene private var hideActions: Boolean = false private var showUi = false - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == android.app.Activity.RESULT_OK) onSelectFolderResult(data) - } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> onSelectFolderResult(data) } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt index d20847d62a..cf848d53dd 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/login/LoginActivity.kt @@ -20,7 +20,7 @@ package com.infomaniak.drive.ui.login import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isInvisible @@ -34,9 +34,7 @@ import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.data.documentprovider.CloudStorageProvider import com.infomaniak.drive.data.models.drive.DriveInfo import com.infomaniak.drive.ui.MainActivity -import com.infomaniak.drive.utils.AccountUtils -import com.infomaniak.drive.utils.clearStack -import com.infomaniak.drive.utils.showSnackbar +import com.infomaniak.drive.utils.* import com.infomaniak.lib.core.InfomaniakCore import com.infomaniak.lib.core.models.ApiError import com.infomaniak.lib.core.models.ApiResponse diff --git a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt index 8f2d8f3e9f..10afdd5986 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt @@ -17,12 +17,11 @@ */ package com.infomaniak.drive.ui.menu.settings -import android.app.Activity import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color import android.os.Bundle -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.core.view.isGone @@ -36,20 +35,14 @@ import com.google.android.material.datepicker.MaterialDatePicker import com.infomaniak.drive.R import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.data.cache.FileController -import com.infomaniak.drive.data.models.MediaFolder -import com.infomaniak.drive.data.models.SyncSettings +import com.infomaniak.drive.data.models.* import com.infomaniak.drive.data.models.SyncSettings.IntervalType import com.infomaniak.drive.data.models.SyncSettings.SavePicturesDate -import com.infomaniak.drive.data.models.UploadFile -import com.infomaniak.drive.data.models.UserDrive import com.infomaniak.drive.ui.BaseActivity import com.infomaniak.drive.ui.fileList.SelectFolderActivity -import com.infomaniak.drive.utils.AccountUtils -import com.infomaniak.drive.utils.DrivePermissions +import com.infomaniak.drive.utils.* import com.infomaniak.drive.utils.SyncUtils.activateAutoSync import com.infomaniak.drive.utils.SyncUtils.disableAutoSync -import com.infomaniak.drive.utils.Utils -import com.infomaniak.drive.utils.startOfTheDay import com.infomaniak.lib.core.utils.FORMAT_DATE_CLEAR_MONTH import com.infomaniak.lib.core.utils.format import com.infomaniak.lib.core.utils.initProgress @@ -67,12 +60,10 @@ class SyncSettingsActivity : BaseActivity() { private var oldSyncSettings: SyncSettings? = null private var editNumber = 0 - private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { result -> - with(result) { - if (resultCode == Activity.RESULT_OK) { - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - syncSettingsViewModel.syncFolder.value = folderId - } + private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { + it.whenResultIsOk { data -> + val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) + syncSettingsViewModel.syncFolder.value = folderId } } diff --git a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt index 1333590f31..bf46481b2e 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt @@ -52,6 +52,8 @@ import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.ImageView import android.widget.LinearLayout +import androidx.activity.result.ActivityResult +import androidx.activity.result.contract.ActivityResultContracts.* import androidx.annotation.DrawableRes import androidx.annotation.IdRes import androidx.biometric.BiometricManager @@ -646,6 +648,10 @@ fun Fragment.navigateToUploadView(folderId: Int, folderName: String? = null) { ) } +fun ActivityResult.whenResultIsOk(completion: (Intent?) -> Unit) { + if (resultCode == Activity.RESULT_OK) data.let(completion::invoke) +} + fun Drive?.getDriveUsers(): List = this?.users?.let { categories -> return@let DriveInfosController.getUsers(ArrayList(categories.drive + categories.account)) } ?: listOf() From 6813f63abdca7317a40d376642ca0932cba649bc Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Tue, 15 Feb 2022 15:38:02 +0100 Subject: [PATCH 020/102] Fix rebase --- .../ActionMultiSelectBottomSheetDialog.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt index bc6835d0bc..091ff30af3 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/ActionMultiSelectBottomSheetDialog.kt @@ -70,7 +70,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { addFavorites.apply { addFavoritesIcon.isEnabled = onlyFavorite val (text, action) = if (onlyFavorite) { - R.string.buttonRemoveFavorites to SelectDialogAction.REMOVE_FAVORITE + R.string.buttonRemoveFavorites to SelectDialogAction.REMOVE_FAVORITES } else { R.string.buttonAddFavorites to SelectDialogAction.ADD_FAVORITES } @@ -135,7 +135,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { private fun onActionSelected(type: SelectDialogAction? = null) { val finalType = when (type) { SelectDialogAction.ADD_FAVORITES -> BulkOperationType.ADD_FAVORITES - SelectDialogAction.REMOVE_FAVORITE -> BulkOperationType.REMOVE_FAVORITES + SelectDialogAction.REMOVE_FAVORITES -> BulkOperationType.REMOVE_FAVORITES SelectDialogAction.ADD_OFFLINE -> BulkOperationType.ADD_OFFLINE SelectDialogAction.REMOVE_OFFLINE -> BulkOperationType.REMOVE_OFFLINE SelectDialogAction.DUPLICATE -> BulkOperationType.COPY @@ -157,7 +157,7 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() { } enum class SelectDialogAction { - ADD_FAVORITES, REMOVE_FAVORITE, ADD_OFFLINE, REMOVE_OFFLINE, DUPLICATE, COLOR_FOLDER + ADD_FAVORITES, REMOVE_FAVORITES, ADD_OFFLINE, REMOVE_OFFLINE, DUPLICATE, COLOR_FOLDER } companion object { From 61a35dc3248612568c546c26dd84c5da5afb0e3e Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Tue, 15 Feb 2022 16:15:55 +0100 Subject: [PATCH 021/102] Optimization --- .../drive/ui/fileList/FileListFragment.kt | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 03a65d8789..ae5d11b354 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -479,16 +479,23 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { moveButtonMultiSelect.setOnClickListener { Utils.moveFileClicked(this, folderId) } menuButtonMultiSelect.setOnClickListener { - with(fileAdapter.getValidItemsSelected()) { - safeNavigate( - FileListFragmentDirections.actionFileListFragmentToActionMultiSelectBottomSheetDialog( - fileIds = this.map { it.id }.toIntArray(), - onlyFolders = this.all { it.isFolder() }, - onlyFavorite = this.all { it.isFavorite }, - onlyOffline = this.all { it.isOffline }, - ) - ) + val fileIds = arrayListOf() + var (onlyFolders, onlyFavorite, onlyOffline) = arrayOf(true, true, true) + fileAdapter.getValidItemsSelected().forEach { + fileIds.add(it.id) + if (!it.isFolder()) onlyFolders = false + if (!it.isFavorite) onlyFavorite = false + if (!it.isOffline) onlyOffline = false } + + safeNavigate( + FileListFragmentDirections.actionFileListFragmentToActionMultiSelectBottomSheetDialog( + fileIds = fileIds.toIntArray(), + onlyFolders = onlyFolders, + onlyFavorite = onlyFavorite, + onlyOffline = onlyOffline, + ) + ) } selectAllButton.apply { From da2da41a45bbacda0c6138a92702e2be0564dc4f Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Tue, 15 Feb 2022 17:49:42 +0100 Subject: [PATCH 022/102] Refactor --- .../com/infomaniak/drive/ui/fileList/FileListFragment.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index ae5d11b354..eaf6462214 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -434,9 +434,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } } - BulkOperationType.ADD_OFFLINE, BulkOperationType.REMOVE_OFFLINE -> { - addOrRemoveSelectedFilesToOffline(file, type == BulkOperationType.ADD_OFFLINE) - } + BulkOperationType.ADD_OFFLINE, BulkOperationType.REMOVE_OFFLINE -> addOrRemoveSelectedFilesToOffline(file, type) BulkOperationType.ADD_FAVORITES -> { mediator.addSource( mainViewModel.addFileToFavorites(file) { @@ -669,11 +667,11 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } } - private fun addOrRemoveSelectedFilesToOffline(file: File, mustAdd: Boolean) { + private fun addOrRemoveSelectedFilesToOffline(file: File, type: BulkOperationType) { if (!file.isFolder()) { val cacheFile = file.getCacheFile(requireContext()) val offlineFile = file.getOfflineFile(requireContext()) - if (mustAdd) { + if (type == BulkOperationType.ADD_OFFLINE) { addSelectedFileToOffline(file, offlineFile, cacheFile) } else { removeSelectedFileFromOffline(file, offlineFile, cacheFile) From eac9c2197c09688abe1de1dea88b4313ac9796f4 Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Tue, 15 Feb 2022 18:18:51 +0100 Subject: [PATCH 023/102] Refactor --- .../com/infomaniak/drive/ui/fileList/FileListFragment.kt | 5 +++-- app/src/main/java/com/infomaniak/drive/utils/Utils.kt | 4 ++-- .../java/com/infomaniak/drive/views/FileInfoActionsView.kt | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index 7a376234bd..f71a34d3e6 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -26,7 +26,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.addCallback -import androidx.activity.result.contract.ActivityResultContracts.* +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.ViewCompat @@ -70,6 +70,7 @@ import com.infomaniak.drive.utils.FilePresenter.openBookmark import com.infomaniak.drive.utils.FilePresenter.openBookmarkIntent import com.infomaniak.drive.utils.Utils.OTHER_ROOT_ID import com.infomaniak.drive.utils.Utils.ROOT_ID +import com.infomaniak.drive.utils.Utils.moveFileClicked import com.infomaniak.lib.core.utils.Utils.createRefreshTimer import com.infomaniak.lib.core.utils.hideProgress import com.infomaniak.lib.core.utils.initProgress @@ -481,7 +482,7 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { deleteButtonMultiSelect.setOnClickListener { performBulkOperation(BulkOperationType.TRASH) } - moveButtonMultiSelect.setOnClickListener { Utils.moveFileClicked(context, folderId, selectFolderResultLauncher) } + moveButtonMultiSelect.setOnClickListener { context?.moveFileClicked(folderId, selectFolderResultLauncher) } menuButtonMultiSelect.setOnClickListener { safeNavigate( diff --git a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt index 118cfffd71..049f40fd59 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt @@ -217,8 +217,8 @@ object Utils { clipboard?.setPrimaryClip(ClipData.newPlainText(text, text)) } - fun moveFileClicked(context: Context?, currentFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { - val intent = Intent(context, SelectFolderActivity::class.java).apply { + fun Context.moveFileClicked(currentFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { + val intent = Intent(this, SelectFolderActivity::class.java).apply { putExtra(SelectFolderActivity.USER_ID_TAG, AccountUtils.currentUserId) putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, AccountUtils.currentDriveId) putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, currentFolder) diff --git a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt index 3cc207a54c..5a1d956286 100644 --- a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt +++ b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt @@ -46,6 +46,7 @@ import com.infomaniak.drive.data.services.DownloadWorker import com.infomaniak.drive.ui.MainViewModel import com.infomaniak.drive.ui.fileList.SelectFolderActivity import com.infomaniak.drive.utils.* +import com.infomaniak.drive.utils.Utils.moveFileClicked import kotlinx.android.synthetic.main.view_file_info_actions.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -429,7 +430,7 @@ class FileInfoActionsView @JvmOverloads constructor( } fun moveFileClicked(context: Context?, idFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { - Utils.moveFileClicked(context, idFolder, selectFolderResultLauncher) + context?.moveFileClicked(idFolder, selectFolderResultLauncher) } fun duplicateFileClicked(context: Context, currentFile: File) { From 5bb3fe839fd7f359d6c9ba44bf40e559d6063fc2 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 16 Feb 2022 08:43:35 +0100 Subject: [PATCH 024/102] Refactor `folderId` Signed-off-by: Kevin Boulongne --- .../java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt | 3 +-- .../infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt | 3 +-- .../java/com/infomaniak/drive/views/FileInfoActionsView.kt | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt index d585fa8a80..a8ec544be0 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt @@ -69,8 +69,7 @@ class SaveExternalFilesActivity : BaseActivity() { private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { it.whenResultIsOk { data -> - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - saveExternalFilesViewModel.folderId.value = folderId + saveExternalFilesViewModel.folderId.value = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt index 10afdd5986..0f0e743c39 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/menu/settings/SyncSettingsActivity.kt @@ -62,8 +62,7 @@ class SyncSettingsActivity : BaseActivity() { private val selectFolderResultLauncher = registerForActivityResult(StartActivityForResult()) { it.whenResultIsOk { data -> - val folderId = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) - syncSettingsViewModel.syncFolder.value = folderId + syncSettingsViewModel.syncFolder.value = data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG) } } diff --git a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt index 5a1d956286..12ccc04808 100644 --- a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt +++ b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt @@ -410,8 +410,8 @@ class FileInfoActionsView @JvmOverloads constructor( } fun onSelectFolderResult(data: Intent?) { - val folderName = data?.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() data?.extras?.getInt(SelectFolderActivity.FOLDER_ID_TAG)?.let { + val folderName = data.extras?.getString(SelectFolderActivity.FOLDER_NAME_TAG).toString() onMoveFile(File(id = it, name = folderName, driveId = AccountUtils.currentDriveId)) } } From 23d9b2a23e689eccae916b3e751f289e06581a86 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 16 Feb 2022 09:48:34 +0100 Subject: [PATCH 025/102] fix file preview for import --- .../com/infomaniak/drive/data/models/File.kt | 17 +++++++++++++++++ .../com/infomaniak/drive/utils/Extensions.kt | 17 +++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/File.kt b/app/src/main/java/com/infomaniak/drive/data/models/File.kt index e3e8d5a726..2fbbf615f5 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/File.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/File.kt @@ -451,5 +451,22 @@ open class File( val mediaFolder = context.externalMediaDirs?.firstOrNull() ?: context.filesDir return java.io.File(mediaFolder, context.getString(R.string.EXPOSED_OFFLINE_DIR)) } + + fun File.getFileTypeFromExtension(): ConvertedType { + return getMimeType().let { + when { + Regex("application/(zip|rar|x-tar|.*compressed|.*archive)").containsMatchIn(it) -> ConvertedType.ARCHIVE + Regex("audio/").containsMatchIn(it) -> ConvertedType.AUDIO + Regex("image/").containsMatchIn(it) -> ConvertedType.IMAGE + Regex("/pdf").containsMatchIn(it) -> ConvertedType.PDF + Regex("presentation").containsMatchIn(it) -> ConvertedType.PRESENTATION + Regex("spreadsheet|excel|comma-separated-values").containsMatchIn(it) -> ConvertedType.SPREADSHEET + Regex("document|text/plain|msword").containsMatchIn(it) -> ConvertedType.TEXT + Regex("video/").containsMatchIn(it) -> ConvertedType.VIDEO + Regex("text/|application/").containsMatchIn(it) -> ConvertedType.CODE + else -> ConvertedType.UNKNOWN + } + } + } } } diff --git a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt index 1333590f31..c6427f4072 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt @@ -86,6 +86,7 @@ import com.google.android.material.textfield.TextInputLayout import com.infomaniak.drive.R import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.data.models.* +import com.infomaniak.drive.data.models.File.Companion.getFileTypeFromExtension import com.infomaniak.drive.data.models.File.VisibilityType import com.infomaniak.drive.data.models.drive.Category import com.infomaniak.drive.data.models.drive.Drive @@ -295,25 +296,25 @@ fun View.setFileItem(file: File, isGrid: Boolean = false) { } file.isDrive() -> filePreview.loadGlide(context.getTintedDrawable(R.drawable.ic_drive, file.driveColor)) else -> { + val fileType = if (file.isFromUploads) file.getFileTypeFromExtension() else file.getFileType() + val isGraphic = fileType == ConvertedType.IMAGE || fileType == ConvertedType.VIDEO when { - file.hasThumbnail && - (isGrid || file.getFileType() == ConvertedType.IMAGE || file.getFileType() == ConvertedType.VIDEO) -> { - filePreview.loadGlideUrl(file.thumbnail(), file.getFileType().icon) + file.hasThumbnail && (isGrid || isGraphic) -> { + filePreview.loadGlideUrl(file.thumbnail(), fileType.icon) } - file.isFromUploads && - (file.getMimeType().startsWith("image/") || file.getMimeType().startsWith("video/")) -> { + file.isFromUploads && isGraphic -> { CoroutineScope(Dispatchers.IO).launch { val bitmap = context.getLocalThumbnail(file) withContext(Dispatchers.Main) { if (filePreview?.isVisible == true && context != null) { - filePreview.loadGlide(bitmap, file.getFileType().icon) + filePreview.loadGlide(bitmap, fileType.icon) } } } } - else -> filePreview.loadGlide(file.getFileType().icon) + else -> filePreview.loadGlide(fileType.icon) } - filePreview2?.loadGlide(file.getFileType().icon) + filePreview2?.loadGlide(fileType.icon) setupFileProgress(file) } } From 3efcfe2c91a7951a66b66b51fc827e982222c4df Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 16 Feb 2022 09:55:37 +0100 Subject: [PATCH 026/102] add missing explanation comment --- .../main/java/com/infomaniak/drive/data/models/File.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/File.kt b/app/src/main/java/com/infomaniak/drive/data/models/File.kt index 2fbbf615f5..f849b4caae 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/File.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/File.kt @@ -451,7 +451,13 @@ open class File( val mediaFolder = context.externalMediaDirs?.firstOrNull() ?: context.filesDir return java.io.File(mediaFolder, context.getString(R.string.EXPOSED_OFFLINE_DIR)) } - + + /** + * This method is here, and not directly a class method in the File class, because of a supposed Realm bug. + * When we try to put it in the File class, the app doesn't build anymore, because of a "broken method". + * This is not the only method in this case, search this comment in the project, and you'll see. + * Realm's Github issue: https://github.com/realm/realm-java/issues/7637 + */ fun File.getFileTypeFromExtension(): ConvertedType { return getMimeType().let { when { From d4fd7c771aa6efe5c3df58026dd6a07db5e32e29 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 16 Feb 2022 14:39:18 +0100 Subject: [PATCH 027/102] Refactor `getFileType` Signed-off-by: Kevin Boulongne --- .../com/infomaniak/drive/data/models/File.kt | 29 +++++++++---------- .../com/infomaniak/drive/utils/Extensions.kt | 9 +++--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/File.kt b/app/src/main/java/com/infomaniak/drive/data/models/File.kt index f849b4caae..2948ff38d9 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/File.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/File.kt @@ -36,6 +36,7 @@ import com.infomaniak.drive.utils.RealmListParceler.FileRealmListParceler import com.infomaniak.drive.utils.RealmListParceler.IntRealmListParceler import com.infomaniak.drive.utils.Utils.INDETERMINATE_PROGRESS import com.infomaniak.drive.utils.Utils.ROOT_ID +import com.infomaniak.drive.utils.contains import com.infomaniak.lib.core.BuildConfig import io.realm.RealmList import io.realm.RealmObject @@ -158,7 +159,7 @@ open class File( fun onlyOfficeUrl() = "${BuildConfig.AUTOLOG_URL}?url=" + ApiRoutes.showOffice(this) fun getFileType(): ConvertedType { - return when (convertedType) { + return if (isFromUploads) getFileTypeFromExtension() else when (convertedType) { ConvertedType.ARCHIVE.value -> ConvertedType.ARCHIVE ConvertedType.AUDIO.value -> ConvertedType.AUDIO ConvertedType.CODE.value -> if (isBookmark()) ConvertedType.URL else ConvertedType.CODE @@ -451,7 +452,7 @@ open class File( val mediaFolder = context.externalMediaDirs?.firstOrNull() ?: context.filesDir return java.io.File(mediaFolder, context.getString(R.string.EXPOSED_OFFLINE_DIR)) } - + /** * This method is here, and not directly a class method in the File class, because of a supposed Realm bug. * When we try to put it in the File class, the app doesn't build anymore, because of a "broken method". @@ -459,19 +460,17 @@ open class File( * Realm's Github issue: https://github.com/realm/realm-java/issues/7637 */ fun File.getFileTypeFromExtension(): ConvertedType { - return getMimeType().let { - when { - Regex("application/(zip|rar|x-tar|.*compressed|.*archive)").containsMatchIn(it) -> ConvertedType.ARCHIVE - Regex("audio/").containsMatchIn(it) -> ConvertedType.AUDIO - Regex("image/").containsMatchIn(it) -> ConvertedType.IMAGE - Regex("/pdf").containsMatchIn(it) -> ConvertedType.PDF - Regex("presentation").containsMatchIn(it) -> ConvertedType.PRESENTATION - Regex("spreadsheet|excel|comma-separated-values").containsMatchIn(it) -> ConvertedType.SPREADSHEET - Regex("document|text/plain|msword").containsMatchIn(it) -> ConvertedType.TEXT - Regex("video/").containsMatchIn(it) -> ConvertedType.VIDEO - Regex("text/|application/").containsMatchIn(it) -> ConvertedType.CODE - else -> ConvertedType.UNKNOWN - } + return when (getMimeType()) { + in Regex("application/(zip|rar|x-tar|.*compressed|.*archive)") -> ConvertedType.ARCHIVE + in Regex("audio/") -> ConvertedType.AUDIO + in Regex("image/") -> ConvertedType.IMAGE + in Regex("/pdf") -> ConvertedType.PDF + in Regex("presentation") -> ConvertedType.PRESENTATION + in Regex("spreadsheet|excel|comma-separated-values") -> ConvertedType.SPREADSHEET + in Regex("document|text/plain|msword") -> ConvertedType.TEXT + in Regex("video/") -> ConvertedType.VIDEO + in Regex("text/|application/") -> ConvertedType.CODE + else -> ConvertedType.UNKNOWN } } } diff --git a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt index c6427f4072..494fa6eb7d 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Extensions.kt @@ -86,7 +86,6 @@ import com.google.android.material.textfield.TextInputLayout import com.infomaniak.drive.R import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.data.models.* -import com.infomaniak.drive.data.models.File.Companion.getFileTypeFromExtension import com.infomaniak.drive.data.models.File.VisibilityType import com.infomaniak.drive.data.models.drive.Category import com.infomaniak.drive.data.models.drive.Drive @@ -296,12 +295,10 @@ fun View.setFileItem(file: File, isGrid: Boolean = false) { } file.isDrive() -> filePreview.loadGlide(context.getTintedDrawable(R.drawable.ic_drive, file.driveColor)) else -> { - val fileType = if (file.isFromUploads) file.getFileTypeFromExtension() else file.getFileType() + val fileType = file.getFileType() val isGraphic = fileType == ConvertedType.IMAGE || fileType == ConvertedType.VIDEO when { - file.hasThumbnail && (isGrid || isGraphic) -> { - filePreview.loadGlideUrl(file.thumbnail(), fileType.icon) - } + file.hasThumbnail && (isGrid || isGraphic) -> filePreview.loadGlideUrl(file.thumbnail(), fileType.icon) file.isFromUploads && isGraphic -> { CoroutineScope(Dispatchers.IO).launch { val bitmap = context.getLocalThumbnail(file) @@ -853,3 +850,5 @@ fun File.getFolderIcon(): Pair { } } } + +operator fun Regex.contains(input: String) = containsMatchIn(input) From 9021792eda99276d6ec1c3e9765a49c89ba78ce2 Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Wed, 16 Feb 2022 14:40:29 +0100 Subject: [PATCH 028/102] Fix typo --- Core | 2 +- .../ui/bottomSheetDialogs/UpdateAvailableBottomSheetDialog.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core b/Core index f1ed05aaec..d89eaf1d24 160000 --- a/Core +++ b/Core @@ -1 +1 @@ -Subproject commit f1ed05aaec4161dfb5da193e49f9e1ac95a6b8c3 +Subproject commit d89eaf1d240cb0d71740d9e07de7d4c38c73a1c9 diff --git a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/UpdateAvailableBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/UpdateAvailableBottomSheetDialog.kt index e52e104ad1..0d2176d1c9 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/UpdateAvailableBottomSheetDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/bottomSheetDialogs/UpdateAvailableBottomSheetDialog.kt @@ -21,7 +21,7 @@ import android.os.Bundle import android.view.View import com.infomaniak.drive.R import com.infomaniak.drive.data.models.UiSettings -import com.infomaniak.lib.core.utils.gotToPlaystore +import com.infomaniak.lib.core.utils.goToPlaystore import kotlinx.android.synthetic.main.fragment_bottom_sheet_information.* class UpdateAvailableBottomSheetDialog : InformationBottomSheetDialog() { @@ -40,7 +40,7 @@ class UpdateAvailableBottomSheetDialog : InformationBottomSheetDialog() { actionButton.setText(R.string.buttonUpdate) actionButton.setOnClickListener { UiSettings(requireContext()).updateLater = false - requireContext().gotToPlaystore() + requireContext().goToPlaystore() dismiss() } } From ffebb51f81a6e7e36f8f8f01674df845688b37ac Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Thu, 10 Feb 2022 13:03:01 +0100 Subject: [PATCH 029/102] Refactored methods to reduce their Cognitive Complexity to the 15 allowed Signed-off-by: Kevin Boulongne --- .../com/infomaniak/drive/ui/MainActivity.kt | 90 ++++++--- .../com/infomaniak/drive/ui/MainViewModel.kt | 59 +++--- .../drive/ui/SaveExternalFilesActivity.kt | 108 +++++----- .../ui/fileList/DownloadProgressDialog.kt | 29 +-- .../drive/ui/fileList/FileAdapter.kt | 162 ++++++++------- .../drive/ui/fileList/FileListFragment.kt | 37 +++- .../ui/fileList/ManageDropboxFragment.kt | 90 +++++---- .../ui/fileList/UploadInProgressFragment.kt | 52 +++-- .../FileShareLinkSettingsFragment.kt | 187 +++++++++++------- .../fileList/fileShare/PermissionsAdapter.kt | 121 +++++++----- .../preview/PreviewPictureFragment.kt | 67 ++++--- 11 files changed, 597 insertions(+), 405 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt index 6709727b5e..6159ef5223 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/MainActivity.kt @@ -37,7 +37,7 @@ import android.util.Log import android.view.View import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.IntentSenderRequest -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toBitmap @@ -45,6 +45,7 @@ import androidx.core.view.get import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager +import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment @@ -119,29 +120,48 @@ class MainActivity : BaseActivity() { downloadReceiver = DownloadReceiver(mainViewModel) fileObserver.startWatching() + val navController = setupNavController() - val navHostFragment = supportFragmentManager.findFragmentById(R.id.hostFragment) as NavHostFragment + setupBottomNavigation(navController) + handleShowProgressIntent(navController) + listenToFilesDeletion() + listenToNetworkStatus() - val navController = navHostFragment.navController.apply { - if (currentDestination == null) { - navigate(graph.startDestinationId) - } + navController.addOnDestinationChangedListener { _, dest, args -> onDestinationChanged(dest, args) } + + setupMainFab(navController) + setupDrivePermissions() + handleInAppReview() + handleUpdates(navController) + + LocalBroadcastManager.getInstance(this).registerReceiver(downloadReceiver, IntentFilter(DownloadReceiver.TAG)) + } + + private fun setupNavController(): NavController { + val navHostFragment = supportFragmentManager.findFragmentById(R.id.hostFragment) as NavHostFragment + return navHostFragment.navController.apply { + if (currentDestination == null) navigate(graph.startDestinationId) } + } - bottomNavigation.setupWithNavControllerCustom(navController) - bottomNavigation.itemIconTintList = ContextCompat.getColorStateList(this, R.color.item_icon_tint_bottom) - bottomNavigation.selectedItemId = UiSettings(this).bottomNavigationSelectedItem - bottomNavigation.setOnItemReselectedListener { item -> - when (item.itemId) { - R.id.fileListFragment, - R.id.favoritesFragment -> { - navController.popBackStack(R.id.homeFragment, false) - navController.navigate(item.itemId) + private fun setupBottomNavigation(navController: NavController) { + bottomNavigation.apply { + setupWithNavControllerCustom(navController) + itemIconTintList = ContextCompat.getColorStateList(this@MainActivity, R.color.item_icon_tint_bottom) + selectedItemId = UiSettings(this@MainActivity).bottomNavigationSelectedItem + setOnItemReselectedListener { item -> + when (item.itemId) { + R.id.fileListFragment, R.id.favoritesFragment -> { + navController.popBackStack(R.id.homeFragment, false) + navController.navigate(item.itemId) + } + else -> navController.popBackStack(item.itemId, false) } - else -> navController.popBackStack(item.itemId, false) } } + } + private fun handleShowProgressIntent(navController: NavController) { intent?.getIntExtra(INTENT_SHOW_PROGRESS, 0)?.let { folderId -> if (folderId > 0) { Sentry.addBreadcrumb(Breadcrumb().apply { @@ -154,15 +174,17 @@ class MainActivity : BaseActivity() { mainViewModel.navigateFileListToFolderId(navController, folderId) } } + } - filesDeletionResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> + private fun listenToFilesDeletion() { + filesDeletionResult = registerForActivityResult(StartIntentSenderForResult()) { result -> if (result.resultCode == RESULT_OK) { - lifecycleScope.launch(Dispatchers.IO) { - UploadFile.deleteAll(uploadedFilesToDelete) - } + lifecycleScope.launch(Dispatchers.IO) { UploadFile.deleteAll(uploadedFilesToDelete) } } } + } + private fun listenToNetworkStatus() { LiveDataNetworkStatus(this).observe(this) { isAvailable -> Log.d("Internet availability", if (isAvailable) "Available" else "Unavailable") Sentry.addBreadcrumb(Breadcrumb().apply { @@ -172,28 +194,34 @@ class MainActivity : BaseActivity() { }) mainViewModel.isInternetAvailable.value = isAvailable if (isAvailable) { - lifecycleScope.launch { - AccountUtils.updateCurrentUserAndDrives(this@MainActivity) - } + lifecycleScope.launch { AccountUtils.updateCurrentUserAndDrives(this@MainActivity) } } } + } - navController.addOnDestinationChangedListener { _, destination, navigationArgs -> - onDestinationChanged(destination, navigationArgs) - } - + private fun setupMainFab(navController: NavController) { mainFab.setOnClickListener { navController.navigate(R.id.addFileBottomSheetDialog) } mainViewModel.currentFolder.observe(this) { file -> mainFab.isEnabled = file?.rights?.newFile == true } + } + private fun setupDrivePermissions() { drivePermissions = DrivePermissions().apply { registerPermissions(this@MainActivity) checkWriteStoragePermission() } + } - if (AppSettings.appLaunches == 20 || (AppSettings.appLaunches != 0 && AppSettings.appLaunches % 100 == 0)) launchInAppReview() + private fun handleInAppReview() { + with(AppSettings) { + if (appLaunches == 20 || (appLaunches != 0 && appLaunches % 100 == 0)) { + launchInAppReview() + } + } + } + private fun handleUpdates(navController: NavController) { if (!UiSettings(this).updateLater || AppSettings.appLaunches % 10 == 0) { checkUpdateIsAvailable { updateIsAvailable -> if (!updateAvailableShow && updateIsAvailable) { @@ -202,8 +230,6 @@ class MainActivity : BaseActivity() { } } } - - LocalBroadcastManager.getInstance(this).registerReceiver(downloadReceiver, IntentFilter(DownloadReceiver.TAG)) } override fun onResume() { @@ -227,6 +253,10 @@ class MainActivity : BaseActivity() { setBottomNavigationUserAvatar(this) startContentObserverService() + handleDeletionOfUploadedPhotos() + } + + private fun handleDeletionOfUploadedPhotos() { if (UploadFile.getAppSyncSettings()?.deleteAfterSync == true && UploadFile.getCurrentUserPendingUploadsCount() == 0) { UploadFile.getAllUploadedFiles()?.let { filesUploadedRecently -> if (filesUploadedRecently.size >= SYNCED_FILES_DELETION_FILES_AMOUNT) { diff --git a/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt b/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt index 307dfb1402..dd3cad3764 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt @@ -269,44 +269,41 @@ class MainViewModel(appContext: Application) : AndroidViewModel(appContext) { } @Deprecated(message = "Only for API 29 and below, otherwise use MediaStore.createDeleteRequest()") - fun deleteSynchronizedFilesOnDevice(filesToDelete: ArrayList) { - viewModelScope.launch(Dispatchers.IO) { - val fileDeleted = arrayListOf() - filesToDelete.forEach { uploadFile -> - val uri = uploadFile.getUriObject() - if (!uri.scheme.equals(ContentResolver.SCHEME_FILE)) { - try { - SyncUtils.checkDocumentProviderPermissions(getContext(), uri) - getContext().contentResolver.query( - uri, arrayOf(MediaStore.Images.Media.DATA), null, null, null - )?.use { cursor -> - if (cursor.moveToFirst()) { - var columnIndex: Int? = null - var pathname: String? = null - try { - columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) - pathname = cursor.getString(columnIndex) - java.io.File(pathname).delete() - getContext().contentResolver.delete(uri, null, null) - fileDeleted.add(uploadFile) - } catch (nullPointerException: NullPointerException) { - Sentry.withScope { scope -> - scope.setExtra("columnIndex", columnIndex.toString()) - scope.setExtra("pathname", pathname.toString()) - scope.setExtra("uploadFileUri", uploadFile.uri) - Sentry.captureException(Exception("deleteSynchronizedFilesOnDevice()")) - } + fun deleteSynchronizedFilesOnDevice(filesToDelete: ArrayList) = viewModelScope.launch(Dispatchers.IO) { + val fileDeleted = arrayListOf() + filesToDelete.forEach { uploadFile -> + val uri = uploadFile.getUriObject() + if (!uri.scheme.equals(ContentResolver.SCHEME_FILE)) { + try { + SyncUtils.checkDocumentProviderPermissions(getContext(), uri) + val query = getContext().contentResolver.query(uri, arrayOf(MediaStore.Images.Media.DATA), null, null, null) + query?.use { cursor -> + if (cursor.moveToFirst()) { + var columnIndex: Int? = null + var pathname: String? = null + try { + columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) + pathname = cursor.getString(columnIndex) + java.io.File(pathname).delete() + getContext().contentResolver.delete(uri, null, null) + fileDeleted.add(uploadFile) + } catch (nullPointerException: NullPointerException) { + Sentry.withScope { scope -> + scope.setExtra("columnIndex", columnIndex.toString()) + scope.setExtra("pathname", pathname.toString()) + scope.setExtra("uploadFileUri", uploadFile.uri) + Sentry.captureException(Exception("deleteSynchronizedFilesOnDevice()")) } } } - } catch (exception: SecurityException) { - exception.printStackTrace() - fileDeleted.add(uploadFile) } + } catch (exception: SecurityException) { + exception.printStackTrace() + fileDeleted.add(uploadFile) } } - UploadFile.deleteAll(fileDeleted) } + UploadFile.deleteAll(fileDeleted) } override fun onCleared() { diff --git a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt index 7ab4af7eae..610b49f556 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/SaveExternalFilesActivity.kt @@ -56,6 +56,7 @@ class SaveExternalFilesActivity : BaseActivity() { private val selectDriveViewModel: SelectDriveViewModel by viewModels() private val saveExternalFilesViewModel: SaveExternalFilesViewModel by viewModels() + private lateinit var saveExternalUriAdapter: SaveExternalUriAdapter private val sharedFolder: java.io.File by lazy { @@ -72,52 +73,67 @@ class SaveExternalFilesActivity : BaseActivity() { if (!isAuth()) return - drivePermissions = DrivePermissions() - drivePermissions.registerPermissions(this, - onPermissionResult = { authorized -> - if (authorized) getFiles() - } - ) - - drivePermissions.checkSyncPermissions() - + setupDrivePermissions() activeDefaultUser() + observeSelectedDrive() + observeFolderId() + setupSaveButton() + } + private fun setupDrivePermissions() { + drivePermissions = DrivePermissions().apply { + registerPermissions( + activity = this@SaveExternalFilesActivity, + onPermissionResult = { authorized -> if (authorized) getFiles() }, + ) + checkSyncPermissions() + } + } + + private fun observeSelectedDrive() { selectDriveViewModel.selectedDrive.observe(this) { - it?.let { - driveIcon.imageTintList = ColorStateList.valueOf(Color.parseColor(it.preferences.color)) - driveName.text = it.name + it?.let { drive -> + driveIcon.imageTintList = ColorStateList.valueOf(Color.parseColor(drive.preferences.color)) + driveName.text = drive.name saveButton.isEnabled = false + pathTitle.isVisible = true + setupSelectPath() UiSettings(this).getSaveExternalFilesPref().let { (userId, driveId, folderId) -> saveExternalFilesViewModel.folderId.value = - if (userId == selectDriveViewModel.selectedUserId.value && driveId == it.id) folderId else null - } - - pathTitle.isVisible = true - selectPath.isVisible = true - selectPath.setOnClickListener { - val intent = Intent(this, SelectFolderActivity::class.java).apply { - putExtra(SelectFolderActivity.USER_ID_TAG, selectDriveViewModel.selectedUserId.value) - putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, selectDriveViewModel.selectedDrive.value?.id) - } - startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + if (userId == selectDriveViewModel.selectedUserId.value && driveId == drive.id) folderId else null } } ?: run { showSelectDrive() } } + } + private fun setupSelectPath() { + selectPath.apply { + isVisible = true + setOnClickListener { + val intent = Intent(this@SaveExternalFilesActivity, SelectFolderActivity::class.java).apply { + putExtra(SelectFolderActivity.USER_ID_TAG, selectDriveViewModel.selectedUserId.value) + putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, selectDriveViewModel.selectedDrive.value?.id) + } + startActivityForResult(intent, SelectFolderActivity.SELECT_FOLDER_REQUEST) + } + } + } + + private fun observeFolderId() { saveExternalFilesViewModel.folderId.observe(this) { folderId -> - val folder = - if (selectDriveViewModel.selectedUserId.value == null || selectDriveViewModel.selectedDrive.value?.id == null || folderId == null) { + val folder = with(selectDriveViewModel) { + if (selectedUserId.value == null || selectedDrive.value?.id == null || folderId == null) { null } else { val userDrive = UserDrive( - userId = selectDriveViewModel.selectedUserId.value!!, - driveId = selectDriveViewModel.selectedDrive.value!!.id + userId = selectedUserId.value!!, + driveId = selectedDrive.value!!.id, ) FileController.getFileById(folderId, userDrive) } + } folder?.let { val folderName = if (folder.isRoot()) { @@ -131,24 +147,28 @@ class SaveExternalFilesActivity : BaseActivity() { pathName.setText(R.string.selectFolderTitle) } } + } - saveButton.initProgress(this) - saveButton.setOnClickListener { - saveButton.showProgress() - if (drivePermissions.checkSyncPermissions()) { - val userId = selectDriveViewModel.selectedUserId.value!! - val driveId = selectDriveViewModel.selectedDrive.value?.id!! - val folderId = saveExternalFilesViewModel.folderId.value!! - - UiSettings(this).setSaveExternalFilesPref(userId, driveId, folderId) - lifecycleScope.launch(Dispatchers.IO) { - if (storeFiles(userId, driveId, folderId)) { - syncImmediately() - finish() - } else { - withContext(Dispatchers.Main) { - saveButton?.hideProgress(R.string.buttonSave) - showSnackbar(R.string.errorSave) + private fun setupSaveButton() { + saveButton.apply { + initProgress(this@SaveExternalFilesActivity) + setOnClickListener { + showProgress() + if (drivePermissions.checkSyncPermissions()) { + val userId = selectDriveViewModel.selectedUserId.value!! + val driveId = selectDriveViewModel.selectedDrive.value?.id!! + val folderId = saveExternalFilesViewModel.folderId.value!! + + UiSettings(this@SaveExternalFilesActivity).setSaveExternalFilesPref(userId, driveId, folderId) + lifecycleScope.launch(Dispatchers.IO) { + if (storeFiles(userId, driveId, folderId)) { + syncImmediately() + finish() + } else { + withContext(Dispatchers.Main) { + this@apply?.hideProgress(R.string.buttonSave) + showSnackbar(R.string.errorSave) + } } } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/DownloadProgressDialog.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/DownloadProgressDialog.kt index 32b8b66c8e..6cd2cae9a2 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/DownloadProgressDialog.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/DownloadProgressDialog.kt @@ -54,20 +54,10 @@ class DownloadProgressDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = with(navigationArgs) { isCancelable = false + FileController.getFileById(fileId, userDrive)?.let { file -> dialogView.icon.setImageResource(file.getFileType().icon) - downloadViewModel.downloadFile(requireContext(), file, userDrive).observe(this@DownloadProgressDialog) { - it?.let { (progress, isComplete) -> - if (isComplete) { - setBackNavigationResult(if (isOpenBookmark) OPEN_BOOKMARK else OPEN_WITH, fileId) - } else { - downloadProgress.progress = progress - } - } ?: run { - requireActivity().showSnackbar(R.string.anErrorHasOccurred) - findNavController().popBackStack() - } - } + observeDownloadedFile(file) } return MaterialAlertDialogBuilder(requireContext(), R.style.DialogStyle) @@ -82,6 +72,21 @@ class DownloadProgressDialog : DialogFragment() { .create() } + private fun observeDownloadedFile(file: File) = with(navigationArgs) { + downloadViewModel.downloadFile(requireContext(), file, userDrive).observe(this@DownloadProgressDialog) { + it?.let { (progress, isComplete) -> + if (isComplete) { + setBackNavigationResult(if (isOpenBookmark) OPEN_BOOKMARK else OPEN_WITH, fileId) + } else { + downloadProgress.progress = progress + } + } ?: run { + requireActivity().showSnackbar(R.string.anErrorHasOccurred) + findNavController().popBackStack() + } + } + } + override fun getView() = dialogView class DownloadViewModel : ViewModel() { diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileAdapter.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileAdapter.kt index 1b7f716b6a..6dababdefd 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileAdapter.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileAdapter.kt @@ -74,32 +74,28 @@ open class FileAdapter( private var showLoading = false private var fileAdapterObserver: RecyclerView.AdapterDataObserver? = null - private fun createFileAdapterObserver(recyclerView: RecyclerView): RecyclerView.AdapterDataObserver { - return object : RecyclerView.AdapterDataObserver() { + private fun createFileAdapterObserver(recyclerView: RecyclerView) = object : RecyclerView.AdapterDataObserver() { - private fun notifyChanged(position: Int) { - recyclerView.post { - if (fileList.isNotEmpty() && position < fileList.count()) notifyItemChanged(position) - } - } + private fun notifyChanged(position: Int) { + recyclerView.post { if (fileList.isNotEmpty() && position < fileList.count()) notifyItemChanged(position) } + } - override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { - if (fileList.isEmpty()) { - onEmptyList?.invoke() - } else if (viewHolderType == DisplayType.LIST && fileList.isNotEmpty()) { - when { - positionStart == 0 -> notifyChanged(0) - positionStart >= fileList.count() -> notifyChanged(fileList.lastIndex) - } + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + if (fileList.isEmpty()) { + onEmptyList?.invoke() + } else if (viewHolderType == DisplayType.LIST && fileList.isNotEmpty()) { + when { + positionStart == 0 -> notifyChanged(0) + positionStart >= fileList.count() -> notifyChanged(fileList.lastIndex) } } + } - override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { - if (viewHolderType == DisplayType.LIST && fileList.count() > 1) { - when { - positionStart == 0 -> notifyChanged(itemCount) - positionStart + itemCount == fileList.count() -> notifyChanged(fileList.lastIndex - itemCount) - } + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + if (viewHolderType == DisplayType.LIST && fileList.count() > 1) { + when { + positionStart == 0 -> notifyChanged(itemCount) + positionStart + itemCount == fileList.count() -> notifyChanged(fileList.lastIndex - itemCount) } } } @@ -261,69 +257,87 @@ open class FileAdapter( } } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { + override fun onBindViewHolder(holder: ViewHolder, position: Int) = with(holder.itemView.fileCardView) { if (getItemViewType(position) != VIEW_TYPE_LOADING) { val file = getFile(position) + val isGrid = viewHolderType == DisplayType.GRID - holder.itemView.fileCardView.apply { - val isGrid = viewHolderType == DisplayType.GRID + if (isGrid) { + if (isHomeOffline) (layoutParams as ConstraintLayout.LayoutParams).dimensionRatio = "2:1" + } else { + setCorners(position, itemCount) + } - if (!isGrid) setCorners(position, itemCount) + setFileItem(file, isGrid) + checkIfEnableFile(file) - if (isGrid && isHomeOffline) { - (layoutParams as ConstraintLayout.LayoutParams).dimensionRatio = "2:1" - } + when { + uploadInProgress && !file.isPendingUploadFolder() -> displayStopUploadButton(position, file) + multiSelectMode -> displayFileChecked(file, isGrid) + else -> displayFilePreview() + } - setFileItem(file, isGrid) + setupFileChecked(file) + setupMenuButton(file) + setupCardClicksListeners(file) + } + } - checkIfEnableFile(file) + private fun MaterialCardView.displayStopUploadButton(position: Int, file: File) { + stopUploadButton?.apply { + setOnClickListener { onStopUploadButtonClicked?.invoke(position, file.name) } + isVisible = true + } + } - when { - uploadInProgress && !file.isPendingUploadFolder() -> { - stopUploadButton?.setOnClickListener { onStopUploadButtonClicked?.invoke(position, file.name) } - stopUploadButton?.isVisible = true - } - multiSelectMode -> { - fileChecked.isChecked = isSelectedFile(file) || allSelected - fileChecked.isVisible = true - filePreview.isVisible = isGrid - } - else -> { - filePreview.isVisible = true - fileChecked.isGone = true - } - } + private fun MaterialCardView.displayFileChecked(file: File, isGrid: Boolean) { + fileChecked.apply { + isChecked = isSelectedFile(file) || allSelected + isVisible = true + } + filePreview.isVisible = isGrid + } - menuButton?.apply { - isGone = uploadInProgress - || selectFolder - || file.isDrive() - || file.isTrashed() - || file.isFromActivities - || file.isFromSearch - || (offlineMode && !file.isOffline) - setOnClickListener { onMenuClicked?.invoke(file) } - } + private fun MaterialCardView.displayFilePreview() { + filePreview.isVisible = true + fileChecked.isGone = true + } - fileChecked.setOnClickListener { - onSelectedFile(file, fileChecked.isChecked) - } - setOnClickListener { - if (multiSelectMode) { - fileChecked.isChecked = !fileChecked.isChecked - onSelectedFile(file, fileChecked.isChecked) - } else { - onFileClicked?.invoke(file) - } - } - setOnLongClickListener { - if (enabledMultiSelectMode) { - fileChecked.isChecked = !fileChecked.isChecked - onSelectedFile(file, fileChecked.isChecked) - if (!multiSelectMode) openMultiSelectMode?.invoke() - true - } else false - } + private fun MaterialCardView.setupFileChecked(file: File) { + fileChecked.apply { setOnClickListener { onSelectedFile(file, isChecked) } } + } + + private fun MaterialCardView.setupMenuButton(file: File) { + menuButton?.apply { + isGone = uploadInProgress + || selectFolder + || file.isDrive() + || file.isTrashed() + || file.isFromActivities + || file.isFromSearch + || (offlineMode && !file.isOffline) + setOnClickListener { onMenuClicked?.invoke(file) } + } + } + + private fun MaterialCardView.setupCardClicksListeners(file: File) { + setOnClickListener { + if (multiSelectMode) { + fileChecked.isChecked = !fileChecked.isChecked + onSelectedFile(file, fileChecked.isChecked) + } else { + onFileClicked?.invoke(file) + } + } + + setOnLongClickListener { + if (enabledMultiSelectMode) { + fileChecked.isChecked = !fileChecked.isChecked + onSelectedFile(file, fileChecked.isChecked) + if (!multiSelectMode) openMultiSelectMode?.invoke() + true + } else { + false } } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt index eaf6462214..db08447089 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/FileListFragment.kt @@ -353,19 +353,36 @@ open class FileListFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { } else { val mediator = mainViewModel.createMultiSelectMediator() enableButtonMultiSelect(false) + sendIndividualActions(selectedFiles, type, mediator, destinationFolder, color) + observeMediator(mediator, fileCount, type, destinationFolder) + } + } - selectedFiles.reversed().forEach { - val file = when { - it.isManagedAndValidByRealm() -> it.realm.copyFromRealm(it, 0) - it.isNotManagedByRealm() -> it - else -> return@forEach - } - sendAction(file, type, mediator, destinationFolder, color) + private fun sendIndividualActions( + selectedFiles: List, + type: BulkOperationType, + mediator: MediatorLiveData>, + destinationFolder: File?, + color: String?, + ) { + selectedFiles.reversed().forEach { + val file = when { + it.isManagedAndValidByRealm() -> it.realm.copyFromRealm(it, 0) + it.isNotManagedByRealm() -> it + else -> return@forEach } + sendAction(file, type, mediator, destinationFolder, color) + } + } - mediator.observe(viewLifecycleOwner) { (success, total) -> - if (total == fileCount) handleBulkActionResult(success, type, destinationFolder) - } + private fun observeMediator( + mediator: MediatorLiveData>, + fileCount: Int, + type: BulkOperationType, + destinationFolder: File?, + ) { + mediator.observe(viewLifecycleOwner) { (success, total) -> + if (total == fileCount) handleBulkActionResult(success, type, destinationFolder) } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/ManageDropboxFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/ManageDropboxFragment.kt index 85a1126ffc..2ab877dcd1 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/ManageDropboxFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/ManageDropboxFragment.kt @@ -106,19 +106,15 @@ open class ManageDropboxFragment : Fragment() { currentDropBox = dropBox?.apply { initLocalValue() } dropBox?.let { - emailWhenFinishedSwitch.isChecked = dropBox.emailWhenFinished - passwordSwitch.isChecked = dropBox.password - expirationDateSwitch.isChecked = dropBox.validUntil != null - limitStorageSwitch.isChecked = dropBox.limitFileSize != null + + setupSwitches(dropBox) + dropBox.limitFileSize?.let { size -> limitStorageValue.setText(Utils.convertBytesToGigaBytes(size).toString()) } if (dropBox.password) { newPasswordButton.isVisible = true needNewPassword = true } - if (expirationDateSwitch.isChecked) expirationDateInput.isVisible = true - if (limitStorageSwitch.isChecked) limitStorageValueLayout.isVisible = true - if (limitStorageSwitch.isChecked) limitStorageValueUnit.isVisible = true expirationDateInput.init(fragmentManager = parentFragmentManager, dropBox.validUntil ?: Date()) { currentDropBox?.newValidUntil = Date(it) @@ -127,6 +123,28 @@ open class ManageDropboxFragment : Fragment() { } } + setupOnCheckedChangeListeners(dropBox) + limitStorageValue.addTextChangedListener { limitStorageChanged(it) } + setupDisableButton(file) + setupSaveButton(file) + } + + private fun setupSwitches(dropBox: DropBox) { + with(dropBox) { + emailWhenFinishedSwitch.isChecked = emailWhenFinished + expirationDateSwitch.isChecked = validUntil != null + limitStorageSwitch.isChecked = limitFileSize != null + passwordSwitch.isChecked = password + } + + if (expirationDateSwitch.isChecked) expirationDateInput.isVisible = true + if (limitStorageSwitch.isChecked) { + limitStorageValueLayout.isVisible = true + limitStorageValueUnit.isVisible = true + } + } + + private fun setupOnCheckedChangeListeners(dropBox: DropBox?) { emailWhenFinishedSwitch.setOnCheckedChangeListener { _, isChecked -> emailSwitched(dropBox, isChecked) } passwordSwitch.setOnCheckedChangeListener { _, isChecked -> passwordSwitched(dropBox, isChecked) } expirationDateSwitch.setOnCheckedChangeListener { _, isChecked -> expirationDateSwitched(dropBox, isChecked) } @@ -136,39 +154,45 @@ open class ManageDropboxFragment : Fragment() { newPasswordButton.isGone = true needNewPassword = false } + } - limitStorageValue.addTextChangedListener { limitStorageChanged(it) } - - disableButton.initProgress(this) - disableButton.setOnClickListener { - disableButton.showProgress(ContextCompat.getColor(requireContext(), R.color.title)) - mainViewModel.deleteDropBox(file).observe(viewLifecycleOwner) { apiResponse -> - if (apiResponse.isSuccess()) { - findNavController().popBackStack() - } else { - requireActivity().showSnackbar(R.string.errorDelete) + private fun setupDisableButton(file: File) { + disableButton.apply { + initProgress(this@ManageDropboxFragment) + setOnClickListener { + showProgress(ContextCompat.getColor(requireContext(), R.color.title)) + mainViewModel.deleteDropBox(file).observe(viewLifecycleOwner) { apiResponse -> + if (apiResponse.isSuccess()) { + findNavController().popBackStack() + } else { + requireActivity().showSnackbar(R.string.errorDelete) + } + hideProgress(R.string.buttonDisableDropBox) } - disableButton.hideProgress(R.string.buttonDisableDropBox) } } + } - saveButton.initProgress(this) - saveButton.setOnClickListener { - currentDropBox?.newPasswordValue = passwordTextInput.text?.toString() - currentDropBox?.newLimitFileSize = - if (limitStorageSwitch.isChecked) { + private fun setupSaveButton(file: File) { + saveButton.apply { + initProgress(this@ManageDropboxFragment) + setOnClickListener { + currentDropBox?.newPasswordValue = passwordTextInput.text?.toString() + currentDropBox?.newLimitFileSize = if (limitStorageSwitch.isChecked) { limitStorageValue.text?.toString()?.toLongOrNull()?.let { Utils.convertGigaByteToBytes(it) } - } else null - - currentDropBox?.let { - saveButton.showProgress() - mainViewModel.updateDropBox(file, it).observe(viewLifecycleOwner) { apiResponse -> - if (apiResponse.isSuccess()) { - findNavController().popBackStack() - } else { - requireActivity().showSnackbar(R.string.errorModification) + } else { + null + } + currentDropBox?.let { + showProgress() + mainViewModel.updateDropBox(file, it).observe(viewLifecycleOwner) { apiResponse -> + if (apiResponse.isSuccess()) { + findNavController().popBackStack() + } else { + requireActivity().showSnackbar(R.string.errorModification) + } + hideProgress(R.string.buttonSave) } - saveButton.hideProgress(R.string.buttonSave) } } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/UploadInProgressFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/UploadInProgressFragment.kt index 05fee13d74..f26cd8fbb5 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/UploadInProgressFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/UploadInProgressFragment.kt @@ -68,10 +68,33 @@ class UploadInProgressFragment : FileListFragment() { super.onViewCreated(view, savedInstanceState) + setupCollapsingToolbarLayout() + observeTrackUploadWorkerProgress() + observeTrackUploadWorkerSucceeded() + observeIndexUploadToDelete() + mainViewModel.refreshActivities.removeObservers(super.getViewLifecycleOwner()) + setupOnStopUploadButtonClicked() + + if (isPendingFolders()) { + fileAdapter.onFileClicked = { navigateToUploadView(it.id, it.name) } + } else { + toolbar.setNavigationOnClickListener { popBackStack() } + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { popBackStack() } + } + + sortLayout.isGone = true + } + + private fun setupCollapsingToolbarLayout() { val fromPendingFolders = findNavController().previousBackStackEntry?.destination?.id == R.id.uploadInProgressFragment - collapsingToolbarLayout.title = - if (folderId > 0 && fromPendingFolders) folderName else getString(R.string.uploadInProgressTitle) + collapsingToolbarLayout.title = if (folderId > 0 && fromPendingFolders) { + folderName + } else { + getString(R.string.uploadInProgressTitle) + } + } + private fun observeTrackUploadWorkerProgress() { requireContext().trackUploadWorkerProgress().observe(viewLifecycleOwner) { val workInfo = it.firstOrNull() ?: return@observe val fileName = workInfo.progress.getString(UploadWorker.FILENAME) ?: return@observe @@ -85,27 +108,29 @@ class UploadInProgressFragment : FileListFragment() { if (!isPendingFolders()) whenAnUploadIsDone(position, fileAdapter.fileList[position].id) fileListViewModel.currentAdapterPendingFiles.value = fileAdapter.getFileObjectsList(null) } else { - fileAdapter.updateFileProgress(position = position, progress = progress) + fileAdapter.updateFileProgress(position, progress) } } Log.d("uploadInProgress", "$fileName $progress%") } + } + private fun observeTrackUploadWorkerSucceeded() { requireContext().trackUploadWorkerSucceeded().observe(viewLifecycleOwner) { fileListViewModel.currentAdapterPendingFiles.value = fileAdapter.getFileObjectsList(null) } + } + private fun observeIndexUploadToDelete() { fileListViewModel.indexUploadToDelete.observe(viewLifecycleOwner) { list -> - list?.let { - list.forEach { (position, fileId) -> - whenAnUploadIsDone(position, fileId) - } + list?.forEach { (position, fileId) -> + whenAnUploadIsDone(position, fileId) } } + } - mainViewModel.refreshActivities.removeObservers(super.getViewLifecycleOwner()) - + private fun setupOnStopUploadButtonClicked() { fileAdapter.onStopUploadButtonClicked = { position, fileName -> pendingUploadFiles.find { it.fileName == fileName }?.let { syncFile -> val title = getString(R.string.uploadInProgressCancelFileUploadTitle, syncFile.fileName) @@ -117,15 +142,6 @@ class UploadInProgressFragment : FileListFragment() { } } } - - if (isPendingFolders()) { - fileAdapter.onFileClicked = { navigateToUploadView(it.id, it.name) } - } else { - toolbar.setNavigationOnClickListener { popBackStack() } - requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { popBackStack() } - } - - sortLayout.isGone = true } override fun setupFileAdapter() { diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt index 97585171ce..9355ee56f8 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt @@ -73,7 +73,116 @@ class FileShareLinkSettingsFragment : Fragment() { } setupUiListeners() + setupFreeAccountUi() + setupShareLinkSettingsUi() + } + + private fun setupUiListeners() { + setupAddPassword() + setupExpirationDate() + setupNewPassword() + setupAllowDownload() + setupBlockComments() + setupBlockUsers() + setupUpgradeOffer() + setupSaveButton() + setupFileShareLinkRights() + } + + private fun setupAddPassword() { + addPasswordSwitch?.setOnCheckedChangeListener { _, isChecked -> + if (shareLink.permission == ShareLink.ShareLinkFilePermission.PUBLIC) { + passwordTextLayout.isVisible = isChecked + } else if (shareLink.permission == ShareLink.ShareLinkFilePermission.PASSWORD) { + passwordTextLayout.isGone = true + newPasswordButton.isVisible = isChecked + } + } + } + + private fun setupExpirationDate() { + addExpirationDateSwitch.setOnCheckedChangeListener { _, isChecked -> + expirationDateInput.isVisible = isChecked + expirationTimeInput.isVisible = isChecked + shareLink.validUntil = if (isChecked) defaultCalendarTimestamp else null + } + } + + private fun setupNewPassword() { + newPasswordButton.setOnClickListener { + newPasswordButton.isGone = true + passwordTextLayout.isVisible = true + } + } + + private fun setupAllowDownload() { + allowDownloadValue.setOnCheckedChangeListener { _, isChecked -> + shareLink.blockDownloads = !isChecked + } + } + + private fun setupBlockComments() { + blockCommentsValue.setOnCheckedChangeListener { _, isChecked -> + shareLink.blockComments = isChecked + } + } + + private fun setupBlockUsers() { + blockUsersConsultValue.setOnCheckedChangeListener { _, isChecked -> + shareLink.blockInformation = isChecked + } + } + + private fun setupUpgradeOffer() { + val upgradeOfferOnClickListener = View.OnClickListener { safeNavigate(R.id.secureLinkShareBottomSheetDialog) } + upgradeOfferPassword.setOnClickListener(upgradeOfferOnClickListener) + upgradeOfferExpirationDate.setOnClickListener(upgradeOfferOnClickListener) + } + + private fun setupSaveButton() { + saveButton.apply { + initProgress(this@FileShareLinkSettingsFragment) + setOnClickListener { + showProgress() + val isValid = checkPasswordStatus() + if (!isValid) { + this?.hideProgress(R.string.buttonSave) + } else { + val file = File(id = navigationArgs.fileId, driveId = navigationArgs.driveId) + shareViewModel.editFileShareLink(file, shareLink).observe(viewLifecycleOwner) { apiResponse -> + if (apiResponse.data == true) { + findNavController().popBackStack() + } else { + requireActivity().showSnackbar(R.string.errorModification) + } + this?.hideProgress(R.string.buttonSave) + } + } + } + } + } + + private fun checkPasswordStatus(): Boolean { + var isValid = true + + if (addPasswordSwitch.isChecked) { + val hasError = passwordEditText.showOrHideEmptyError() + isValid = !(hasError && passwordTextLayout.isVisible) + + val password = passwordEditText.text + if (password?.isNotBlank() == true) shareLink.apply { + this.password = password.toString() + this.permission = ShareLink.ShareLinkFilePermission.PASSWORD + } + + } else { + shareLink.permission = ShareLink.ShareLinkFilePermission.PUBLIC + } + + return isValid + } + private fun setupFileShareLinkRights() { fileShareLinkRights.setOnClickListener { val permissionsGroup = if (navigationArgs.isFolder) SelectPermissionBottomSheetDialog.PermissionsGroup.SHARE_LINK_FOLDER_OFFICE @@ -86,7 +195,9 @@ class FileShareLinkSettingsFragment : Fragment() { ) ) } + } + private fun setupFreeAccountUi() { if (AccountUtils.getCurrentDrive()?.pack == Drive.DrivePack.FREE.value) { addPasswordLayout.apply { @@ -101,8 +212,6 @@ class FileShareLinkSettingsFragment : Fragment() { upgradeOfferExpirationDate.isVisible = true } } - - setupShareLinkSettingsUi() } private fun setupShareLinkSettingsUi() { @@ -170,78 +279,4 @@ class FileShareLinkSettingsFragment : Fragment() { ) } } - - private fun setupUiListeners() { - - addPasswordSwitch?.setOnCheckedChangeListener { _, isChecked -> - if (shareLink.permission == ShareLink.ShareLinkFilePermission.PUBLIC) { - passwordTextLayout.isVisible = isChecked - } else if (shareLink.permission == ShareLink.ShareLinkFilePermission.PASSWORD) { - passwordTextLayout.isGone = true - newPasswordButton.isVisible = isChecked - } - } - - addExpirationDateSwitch.setOnCheckedChangeListener { _, isChecked -> - expirationDateInput.isVisible = isChecked - expirationTimeInput.isVisible = isChecked - shareLink.validUntil = if (isChecked) defaultCalendarTimestamp else null - } - - newPasswordButton.setOnClickListener { - newPasswordButton.isGone = true - passwordTextLayout.isVisible = true - } - - allowDownloadValue.setOnCheckedChangeListener { _, isChecked -> - shareLink.blockDownloads = !isChecked - } - - blockCommentsValue.setOnCheckedChangeListener { _, isChecked -> - shareLink.blockComments = isChecked - } - - blockUsersConsultValue.setOnCheckedChangeListener { _, isChecked -> - shareLink.blockInformation = isChecked - } - - val upgradeOfferOnClickListener = View.OnClickListener { safeNavigate(R.id.secureLinkShareBottomSheetDialog) } - upgradeOfferPassword.setOnClickListener(upgradeOfferOnClickListener) - upgradeOfferExpirationDate.setOnClickListener(upgradeOfferOnClickListener) - - saveButton.initProgress(this) - saveButton.setOnClickListener { - saveButton.showProgress() - - var isValid = true - if (addPasswordSwitch.isChecked) { - - val hasError = passwordEditText.showOrHideEmptyError() - isValid = !(hasError && passwordTextLayout.isVisible) - - val password = passwordEditText.text - if (password?.isNotBlank() == true) shareLink.apply { - this.password = password.toString() - this.permission = ShareLink.ShareLinkFilePermission.PASSWORD - } - - } else { - shareLink.permission = ShareLink.ShareLinkFilePermission.PUBLIC - } - - if (!isValid) { - saveButton?.hideProgress(R.string.buttonSave) - } else { - val file = File(id = navigationArgs.fileId, driveId = navigationArgs.driveId) - shareViewModel.editFileShareLink(file, shareLink).observe(viewLifecycleOwner) { apiResponse -> - if (apiResponse.data == true) { - findNavController().popBackStack() - } else { - requireActivity().showSnackbar(R.string.errorModification) - } - saveButton?.hideProgress(R.string.buttonSave) - } - } - } - } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/PermissionsAdapter.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/PermissionsAdapter.kt index a54db25b44..66503c4d8b 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/PermissionsAdapter.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/PermissionsAdapter.kt @@ -30,7 +30,7 @@ import com.infomaniak.drive.R import com.infomaniak.drive.data.models.DriveUser import com.infomaniak.drive.data.models.File.FolderPermission import com.infomaniak.drive.data.models.Permission -import com.infomaniak.drive.data.models.Shareable +import com.infomaniak.drive.data.models.Shareable.ShareablePermission import com.infomaniak.drive.utils.AccountUtils import com.infomaniak.drive.utils.loadAvatar import com.infomaniak.drive.utils.loadGlide @@ -68,67 +68,84 @@ class PermissionsAdapter( notifyItemInserted(permissionList.size) } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { + override fun onBindViewHolder(holder: ViewHolder, position: Int) = with(holder.itemView) { val permission = permissionList[position] - holder.itemView.apply { - permissionCard.apply { - setupSelection(position == selectionPosition) - setOnClickListener { - if (selectionPosition != position) { - onPermissionChanged(permission) - selectionPosition = position - notifyItemRangeChanged(0, itemCount) - } + + permissionCard.apply { + setupSelection(position == selectionPosition) + setOnClickListener { + if (selectionPosition != position) { + onPermissionChanged(permission) + selectionPosition = position + notifyItemRangeChanged(0, itemCount) } } - permissionTitle.setText(permission.translation) - permissionDescription.text = context.getString(permission.description, AccountUtils.getCurrentDrive()?.name) - - val shapeAppearanceModel = ShapeAppearanceModel() - .toBuilder() - .setAllCornerSizes(RelativeCornerSize(0.5F)) - .build() - mainIcon.shapeAppearanceModel = shapeAppearanceModel - - when (permission) { - FolderPermission.ONLY_ME -> { - currentUser?.let { user -> mainIcon.loadAvatar(user) } - permissionDescription.isGone = true - } - FolderPermission.INHERIT -> { - if (sharedUsers.isNotEmpty()) { - sharedUsers.firstOrNull()?.let { firstUser -> mainIcon.loadAvatar(firstUser) } - secondIcon.apply { - sharedUsers.getOrNull(1)?.let { user -> - isVisible = true - loadAvatar(user) - } - } - thirdIcon.apply { - if (sharedUsers.size > 2) { - isVisible = true - remainingText.isVisible = true - remainingText.text = "+${sharedUsers.size - 2}" - } - } - } + } + + setupTexts(permission) + setupMainIcon() + + when (permission) { + FolderPermission.ONLY_ME -> setupOnlyMePermissionUi() + FolderPermission.INHERIT -> setupInheritPermissionUi() + else -> setupOthersPermissionUi(permission) + } + } + + private fun View.setupTexts(permission: Permission) { + permissionTitle.setText(permission.translation) + permissionDescription.text = context.getString(permission.description, AccountUtils.getCurrentDrive()?.name) + } + + private fun View.setupMainIcon() { + mainIcon.shapeAppearanceModel = ShapeAppearanceModel() + .toBuilder() + .setAllCornerSizes(RelativeCornerSize(0.5F)) + .build() + } + + private fun View.setupOnlyMePermissionUi() { + currentUser?.let { user -> mainIcon.loadAvatar(user) } + permissionDescription.isGone = true + } + + private fun View.setupInheritPermissionUi() { + if (sharedUsers.isNotEmpty()) { + + sharedUsers.firstOrNull()?.let { firstUser -> mainIcon.loadAvatar(firstUser) } + + secondIcon.apply { + sharedUsers.getOrNull(1)?.let { user -> + isVisible = true + loadAvatar(user) } - else -> { - mainIcon.loadGlide(permission.icon) - mainIcon.shapeAppearanceModel = ShapeAppearanceModel() - - when { - permission == Shareable.ShareablePermission.MANAGE && isExternalUser -> { - enableViewHolder(false) - userExternalWarning.isVisible = true - } - else -> enableViewHolder(true) + } + + thirdIcon.apply { + if (sharedUsers.size > 2) { + isVisible = true + remainingText.apply { + isVisible = true + text = "+${sharedUsers.size - 2}" } } } } } + private fun View.setupOthersPermissionUi(permission: Permission) { + mainIcon.loadGlide(permission.icon) + mainIcon.shapeAppearanceModel = ShapeAppearanceModel() + + when { + permission == ShareablePermission.MANAGE && isExternalUser -> { + enableViewHolder(false) + userExternalWarning.isVisible = true + } + else -> enableViewHolder(true) + } + } + private fun View.enableViewHolder(enabled: Boolean) { isEnabled = enabled disabled.isGone = enabled diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewPictureFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewPictureFragment.kt index e8e2174efc..8b05954dd2 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewPictureFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/preview/PreviewPictureFragment.kt @@ -19,6 +19,7 @@ package com.infomaniak.drive.ui.fileList.preview import android.annotation.SuppressLint import android.os.Bundle +import android.os.CountDownTimer import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -29,6 +30,7 @@ import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import coil.Coil import coil.load +import coil.request.Disposable import coil.request.ImageRequest import com.infomaniak.drive.R import com.infomaniak.lib.core.utils.Utils.createRefreshTimer @@ -45,7 +47,6 @@ class PreviewPictureFragment : PreviewFragment() { return inflater.inflate(R.layout.fragment_preview_picture, container, false) } - @SuppressLint("ClickableViewAccessibility") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -60,40 +61,56 @@ class PreviewPictureFragment : PreviewFragment() { setOnClickListener { (parentFragment as? PreviewSliderFragment)?.openWithClicked() } } + val offlineFile = if (file.isOffline) { + file.getOfflineFile(requireContext(), previewSliderViewModel.userDrive.userId) + } else { + null + } val imageViewDisposable = imageView.load(file.thumbnail()) { placeholder(R.drawable.coil_hack) } - val offlineFile = - if (file.isOffline) file.getOfflineFile(requireContext(), previewSliderViewModel.userDrive.userId) else null if (offlineFile != null && file.isOfflineAndIntact(offlineFile)) { if (!imageViewDisposable.isDisposed) imageViewDisposable.dispose() imageView?.setImageURI(offlineFile.toUri()) } else { - val imageLoader = Coil.imageLoader(requireContext()) - val previewRequest = ImageRequest.Builder(requireContext()) - .data(file.imagePreview()) - .listener( - onError = { _, _ -> - fileName?.text = file.name - previewDescription?.isVisible = true - bigOpenWithButton?.isVisible = true - imageView?.isGone = true - }, - onSuccess = { _, _ -> - timer.cancel() - noThumbnailLayout?.isGone = true - } - ) - .build() + loadImage(timer, imageViewDisposable) + } - lifecycleScope.launch(Dispatchers.IO) { - imageLoader.execute(previewRequest).drawable?.let { drawable -> - if (!imageViewDisposable.isDisposed) imageViewDisposable.dispose() - withContext(Dispatchers.Main) { imageView?.load(drawable) { crossfade(false) } } - } + container?.layoutTransition?.setAnimateParentHierarchy(false) + setupImageListeners() + } + + private fun loadImage(timer: CountDownTimer, imageViewDisposable: Disposable) { + val imageLoader = Coil.imageLoader(requireContext()) + val previewRequest = buildPreviewRequest(timer) + + lifecycleScope.launch(Dispatchers.IO) { + imageLoader.execute(previewRequest).drawable?.let { drawable -> + if (!imageViewDisposable.isDisposed) imageViewDisposable.dispose() + withContext(Dispatchers.Main) { imageView?.load(drawable) { crossfade(false) } } } } + } - container?.layoutTransition?.setAnimateParentHierarchy(false) + private fun buildPreviewRequest(timer: CountDownTimer): ImageRequest { + return ImageRequest.Builder(requireContext()) + .data(file.imagePreview()) + .listener( + onError = { _, _ -> + fileName?.text = file.name + previewDescription?.isVisible = true + bigOpenWithButton?.isVisible = true + imageView?.isGone = true + }, + onSuccess = { _, _ -> + timer.cancel() + noThumbnailLayout?.isGone = true + }, + ) + .build() + } + + @SuppressLint("ClickableViewAccessibility") + private fun setupImageListeners() { imageView.apply { setOnTouchListener { view, event -> From d6c52462c10cc67a9814ed58e2274e297a77abe7 Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Tue, 15 Feb 2022 14:25:14 +0100 Subject: [PATCH 030/102] Better call saul --- .../ui/fileList/fileShare/FileShareLinkSettingsFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt index 9355ee56f8..f63730c380 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/fileShare/FileShareLinkSettingsFragment.kt @@ -146,7 +146,7 @@ class FileShareLinkSettingsFragment : Fragment() { showProgress() val isValid = checkPasswordStatus() if (!isValid) { - this?.hideProgress(R.string.buttonSave) + hideProgress(R.string.buttonSave) } else { val file = File(id = navigationArgs.fileId, driveId = navigationArgs.driveId) shareViewModel.editFileShareLink(file, shareLink).observe(viewLifecycleOwner) { apiResponse -> @@ -155,7 +155,7 @@ class FileShareLinkSettingsFragment : Fragment() { } else { requireActivity().showSnackbar(R.string.errorModification) } - this?.hideProgress(R.string.buttonSave) + saveButton?.hideProgress(R.string.buttonSave) } } } From 5281cf5fc508292a61a01027b56986905c547b38 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Wed, 16 Feb 2022 17:32:10 +0100 Subject: [PATCH 031/102] Ignore sync media folder exceptions and add more sentry log for "external_primary not found" Signed-off-by: Abdourahamane BOINAIDI --- .../drive/data/services/UploadWorker.kt | 122 +++++++++++------- 1 file changed, 72 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt index 27894c942d..40eb2dfce9 100644 --- a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt +++ b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt @@ -316,40 +316,50 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor Log.d(TAG, "checkLocalLastMedias> started with ${UploadFile.getLastDate(applicationContext)}") MediaFolder.getAllSyncedFolders().forEach { mediaFolder -> + // Add log + Sentry.addBreadcrumb(Breadcrumb().apply { + category = BREADCRUMB_TAG + message = "sync ${mediaFolder.name}" + level = SentryLevel.DEBUG + }) Log.d(TAG, "checkLocalLastMedias> sync folder ${mediaFolder.name}_${mediaFolder.id}") + + // Sync media folder var isNotPending = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) "AND ${MediaStore.Images.Media.IS_PENDING} = 0" else "" customSelection = "$selection AND $IMAGES_BUCKET_ID = ? $isNotPending" customArgs = args + mediaFolder.id.toString() - runCatching { - val getLastImagesOperation = getLocalLastMediasAsync( + val getLastImagesOperation = getLocalLastMediasAsync( + syncSettings = syncSettings, + contentUri = MediaFoldersProvider.imagesExternalUri, + selection = customSelection, + args = customArgs, + mediaFolder = mediaFolder + ) + jobs.add(getLastImagesOperation) + + if (syncSettings.syncVideo) { + isNotPending = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + "AND ${MediaStore.Video.Media.IS_PENDING} = 0" else "" + customSelection = "$selection AND $VIDEO_BUCKET_ID = ? $isNotPending" + + val getLastVideosOperation = getLocalLastMediasAsync( syncSettings = syncSettings, - contentUri = MediaFoldersProvider.imagesExternalUri, + contentUri = MediaFoldersProvider.videosExternalUri, selection = customSelection, args = customArgs, mediaFolder = mediaFolder ) - jobs.add(getLastImagesOperation) - - if (syncSettings.syncVideo) { - isNotPending = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - "AND ${MediaStore.Video.Media.IS_PENDING} = 0" else "" - customSelection = "$selection AND $VIDEO_BUCKET_ID = ? $isNotPending" - - val getLastVideosOperation = getLocalLastMediasAsync( - syncSettings = syncSettings, - contentUri = MediaFoldersProvider.videosExternalUri, - selection = customSelection, - args = customArgs, - mediaFolder = mediaFolder - ) - jobs.add(getLastVideosOperation) - } + jobs.add(getLastVideosOperation) } } - jobs.joinAll() + try { + jobs.joinAll() + } catch (exception: Exception) { + Log.e("sisi", exception.message ?: "") + } } private fun CoroutineScope.getLocalLastMediasAsync( @@ -364,40 +374,52 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor MediaStore.MediaColumns.DATE_ADDED + " ASC, " + MediaStore.MediaColumns.DATE_MODIFIED + " ASC" - contentResolver.query(contentUri, null, selection, args, sortOrder) - ?.use { cursor -> - Log.d(TAG, "getLocalLastMediasAsync > from ${mediaFolder.name} ${cursor.count} found") - while (cursor.moveToNext()) { - val uri = cursor.uri(contentUri) - - val (fileCreatedAt, fileModifiedAt) = SyncUtils.getFileDates(cursor) - val fileName = SyncUtils.getFileName(cursor) - val fileSize = fileDescriptorSize(uri) ?: SyncUtils.getFileSize(cursor) - - Log.d(TAG, "getLocalLastMediasAsync > ${mediaFolder.name}/$fileName found") - - if (fileName != null && UploadFile.canUpload(uri, fileModifiedAt) && fileSize > 0) { - UploadFile.deleteIfExists(uri) - UploadFile( - uri = uri.toString(), - driveId = syncSettings.driveId, - fileCreatedAt = fileCreatedAt, - fileModifiedAt = fileModifiedAt, - fileName = fileName, - fileSize = fileSize, - remoteFolder = syncSettings.syncFolder, - userId = syncSettings.userId - ).apply { - createSubFolder(mediaFolder.name, syncSettings.createDatedSubFolders) - store() + runCatching { + contentResolver.query(contentUri, null, selection, args, sortOrder) + ?.use { cursor -> + Log.d(TAG, "getLocalLastMediasAsync > from ${mediaFolder.name} ${cursor.count} found") + while (cursor.moveToNext()) { + val uri = cursor.uri(contentUri) + + val (fileCreatedAt, fileModifiedAt) = SyncUtils.getFileDates(cursor) + val fileName = SyncUtils.getFileName(cursor) + val fileSize = fileDescriptorSize(uri) ?: SyncUtils.getFileSize(cursor) + + Log.d(TAG, "getLocalLastMediasAsync > ${mediaFolder.name}/$fileName found") + + if (fileName != null && UploadFile.canUpload(uri, fileModifiedAt) && fileSize > 0) { + UploadFile.deleteIfExists(uri) + UploadFile( + uri = uri.toString(), + driveId = syncSettings.driveId, + fileCreatedAt = fileCreatedAt, + fileModifiedAt = fileModifiedAt, + fileName = fileName, + fileSize = fileSize, + remoteFolder = syncSettings.syncFolder, + userId = syncSettings.userId + ).apply { + createSubFolder(mediaFolder.name, syncSettings.createDatedSubFolders) + store() + } + + UploadFile.setAppSyncSettings(syncSettings.apply { + if (fileModifiedAt > lastSync) lastSync = fileModifiedAt + }) } - - UploadFile.setAppSyncSettings(syncSettings.apply { - if (fileModifiedAt > lastSync) lastSync = fileModifiedAt - }) } } + }.onFailure { exception -> + // Catch Api>=29 for exception {Volume external_primary not found}, Adding logs to get more information + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && exception is IllegalArgumentException) { + Sentry.withScope { scope -> + val volumeNames = MediaStore.getExternalVolumeNames(applicationContext).joinToString() + scope.setExtra("uri", contentUri.toString()) + scope.setExtra("folder", mediaFolder.name) + scope.setExtra("volume names", volumeNames) + } } + } } companion object { From 4cd9052737d25f2aa19d22e24e52ccdbf00b7042 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Wed, 16 Feb 2022 17:42:47 +0100 Subject: [PATCH 032/102] Reduce sonar method complexity Signed-off-by: Abdourahamane BOINAIDI --- .../drive/data/services/UploadWorker.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt index 40eb2dfce9..fbf7d05c57 100644 --- a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt +++ b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt @@ -410,14 +410,18 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } }.onFailure { exception -> - // Catch Api>=29 for exception {Volume external_primary not found}, Adding logs to get more information - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && exception is IllegalArgumentException) { - Sentry.withScope { scope -> - val volumeNames = MediaStore.getExternalVolumeNames(applicationContext).joinToString() - scope.setExtra("uri", contentUri.toString()) - scope.setExtra("folder", mediaFolder.name) - scope.setExtra("volume names", volumeNames) - } + syncMediaFolderFailure(exception, contentUri, mediaFolder) + } + } + + private fun syncMediaFolderFailure(exception: Throwable, contentUri: Uri, mediaFolder: MediaFolder) { + // Catch Api>=29 for exception {Volume external_primary not found}, Adding logs to get more information + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && exception is IllegalArgumentException) { + Sentry.withScope { scope -> + val volumeNames = MediaStore.getExternalVolumeNames(applicationContext).joinToString() + scope.setExtra("uri", contentUri.toString()) + scope.setExtra("folder", mediaFolder.name) + scope.setExtra("volume names", volumeNames) } } } From 3ea2f90e2aa57509225d58f60aada095f5b201ac Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Wed, 16 Feb 2022 17:43:40 +0100 Subject: [PATCH 033/102] Remove useless logs Signed-off-by: Abdourahamane BOINAIDI --- .../java/com/infomaniak/drive/data/services/UploadWorker.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt index fbf7d05c57..d81f439239 100644 --- a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt +++ b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt @@ -355,11 +355,7 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } - try { - jobs.joinAll() - } catch (exception: Exception) { - Log.e("sisi", exception.message ?: "") - } + jobs.joinAll() } private fun CoroutineScope.getLocalLastMediasAsync( From 3fe77d463fe9c782a37dfbf835a89630e6691a04 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Thu, 17 Feb 2022 11:18:53 +0100 Subject: [PATCH 034/102] Refactor + Bumped RealmGradlePlugin to 10.10.1 Signed-off-by: Kevin Boulongne --- app/build.gradle | 31 +++---- .../drive/ui/fileList/SelectFolderActivity.kt | 27 ++++--- .../drive/ui/fileList/SelectFolderFragment.kt | 81 ++++++++----------- .../java/com/infomaniak/drive/utils/Utils.kt | 4 +- .../drive/views/FileInfoActionsView.kt | 8 +- app/src/main/res/navigation/select_folder.xml | 2 +- build.gradle | 23 +++--- 7 files changed, 78 insertions(+), 98 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1ac4e12963..c778f381e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,16 +6,17 @@ apply plugin: 'androidx.navigation.safeargs.kotlin' apply plugin: 'realm-android' android { + compileSdkVersion 31 defaultConfig { - applicationId "com.infomaniak.drive" + applicationId 'com.infomaniak.drive' minSdkVersion 21 targetSdkVersion 31 versionCode 4_01_000_06 - versionName "4.1.0" + versionName '4.1.0' - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' buildConfigField 'String', 'CLIENT_ID', '"9473D73C-C20F-4971-9E10-D957C563FA68"' buildConfigField 'String', 'DRIVE_API', '"https://drive.infomaniak.com/drive/"' @@ -38,9 +39,7 @@ android { targetCompatibility rootProject.ext.java_version } - kotlinOptions { - jvmTarget = rootProject.ext.java_version - } + kotlinOptions { jvmTarget = rootProject.ext.java_version } buildTypes { release { @@ -49,17 +48,15 @@ android { } } - flavorDimensions "distribution" + flavorDimensions 'distribution' productFlavors { standard { - dimension "distribution" + dimension 'distribution' apply plugin: 'com.google.gms.google-services' } - fdroid { - dimension "distribution" - } + fdroid { dimension 'distribution' } preprod { - dimension "distribution" + dimension 'distribution' buildConfigField 'String', 'DRIVE_API', '"https://drive.preprod.dev.infomaniak.ch/drive/"' buildConfigField 'String', 'DRIVE_API_V2', '"https://drive.preprod.dev.infomaniak.ch/2/drive/"' } @@ -67,7 +64,7 @@ android { gradle.buildFinished { BuildResult buildResult -> try { - "say \"Ok\"".execute() + 'say \"Ok\"'.execute() } catch (Throwable ignored) { } } @@ -94,7 +91,7 @@ sentry { } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':Core') def work_version = '2.7.1' @@ -124,13 +121,11 @@ dependencies { implementation "io.coil-kt:coil-gif:$coil_version" def glide_version = '4.12.0' - implementation("com.github.bumptech.glide:glide:$glide_version") { - exclude group: "com.android.support" - } + implementation("com.github.bumptech.glide:glide:$glide_version") { exclude group: 'com.android.support' } implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version" kapt "com.github.bumptech.glide:compiler:$glide_version" - implementation "io.realm:android-adapters:4.0.0" + implementation 'io.realm:android-adapters:4.0.0' standardImplementation 'com.google.android.play:core:1.10.3' standardImplementation 'com.google.firebase:firebase-messaging-ktx:23.0.0' diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt index fe98dc6fbc..15e3275c1a 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderActivity.kt @@ -48,23 +48,28 @@ class SelectFolderActivity : BaseActivity() { const val BULK_OPERATION_CUSTOM_TAG = "bulk_operation_type" } - override fun onCreate(savedInstanceState: Bundle?) { - val userId = intent.extras?.getInt(USER_ID_TAG) ?: throw MissingFormatArgumentException(USER_ID_TAG) - val driveId = intent.extras?.getInt(USER_DRIVE_ID_TAG) ?: throw MissingFormatArgumentException(USER_DRIVE_ID_TAG) - val customArgs = intent.extras?.getBundle(CUSTOM_ARGS_TAG) - val userDrive = UserDrive(userId, driveId) + override fun onCreate(savedInstanceState: Bundle?) = with(intent) { + val userId = extras?.getInt(USER_ID_TAG) ?: throw MissingFormatArgumentException(USER_ID_TAG) + val driveId = extras?.getInt(USER_DRIVE_ID_TAG) ?: throw MissingFormatArgumentException(USER_DRIVE_ID_TAG) + val customArgs = extras?.getBundle(CUSTOM_ARGS_TAG) + val currentUserDrive = UserDrive(userId, driveId) - mainViewModel.selectFolderUserDrive = userDrive - saveExternalViewModel.userDrive = userDrive - saveExternalViewModel.currentDrive = DriveInfosController.getDrives(userId, driveId).firstOrNull() - saveExternalViewModel.disableSelectedFolder = intent.extras?.getInt(DISABLE_SELECTED_FOLDER_TAG) + mainViewModel.selectFolderUserDrive = currentUserDrive + + saveExternalViewModel.apply { + userDrive = currentUserDrive + currentDrive = DriveInfosController.getDrives(userId, driveId).firstOrNull() + disableSelectedFolderId = extras?.getInt(DISABLE_SELECTED_FOLDER_TAG) + } super.onCreate(savedInstanceState) setContentView(R.layout.activity_select_folder) + setSaveButton(customArgs) + } + private fun setSaveButton(customArgs: Bundle?) { saveButton.setOnClickListener { val currentFragment = hostFragment.childFragmentManager.fragments.first() as SelectFolderFragment - val intent = Intent().apply { putExtra(FOLDER_ID_TAG, currentFragment.folderId) putExtra(FOLDER_NAME_TAG, currentFragment.folderName) @@ -90,6 +95,6 @@ class SelectFolderActivity : BaseActivity() { class SaveExternalViewModel : ViewModel() { var userDrive: UserDrive? = null var currentDrive: Drive? = null - var disableSelectedFolder: Int? = null + var disableSelectedFolderId: Int? = null } } diff --git a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderFragment.kt b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderFragment.kt index c39c2cae4a..7821101853 100644 --- a/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderFragment.kt +++ b/app/src/main/java/com/infomaniak/drive/ui/fileList/SelectFolderFragment.kt @@ -26,6 +26,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.infomaniak.drive.R import com.infomaniak.drive.data.cache.FileController +import com.infomaniak.drive.data.models.Rights import com.infomaniak.drive.ui.fileList.SelectFolderActivity.SaveExternalViewModel import com.infomaniak.drive.utils.Utils import com.infomaniak.drive.utils.Utils.ROOT_ID @@ -50,66 +51,50 @@ class SelectFolderFragment : FileListFragment() { collapsingToolbarLayout.title = getString(R.string.selectFolderTitle) - toolbar.menu.apply { - findItem(R.id.addFolderItem).apply { - setOnMenuItemClickListener { - val selectFolderActivity = requireActivity() as? SelectFolderActivity - if (FileController.getFileById(folderId, userDrive)?.rights?.newFolder == true) { - selectFolderActivity?.hideSaveButton() - safeNavigate( - SelectFolderFragmentDirections.actionSelectFolderFragmentToNewFolderFragment( - parentFolderId = folderId, - userDrive = userDrive - ) + toolbar.menu.findItem(R.id.addFolderItem).apply { + setOnMenuItemClickListener { + val selectFolderActivity = requireActivity() as? SelectFolderActivity + if (FileController.getFileById(folderId, userDrive)?.rights?.newFolder == true) { + selectFolderActivity?.hideSaveButton() + safeNavigate( + SelectFolderFragmentDirections.actionSelectFolderFragmentToNewFolderFragment( + parentFolderId = folderId, + userDrive = userDrive, ) - } else { - selectFolderActivity?.showSnackbar(R.string.allFileAddRightError) - } - true + ) + } else { + selectFolderActivity?.showSnackbar(R.string.allFileAddRightError) } - isVisible = true + true } + isVisible = true } - toolbar.setNavigationOnClickListener { - onBackPressed() - } - - requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { - onBackPressed() - } + toolbar.setNavigationOnClickListener { onBackPressed() } + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBackPressed() } - fileAdapter.selectFolder = true - fileAdapter.onFileClicked = { file -> - when { - file.isFolder() -> { - if (!file.isDisabled()) { - fileListViewModel.cancelDownloadFiles() - safeNavigate( - SelectFolderFragmentDirections.fileListFragmentToFileListFragment( - folderId = file.id, - folderName = file.name - ) - ) - } + fileAdapter.apply { + selectFolder = true + onFileClicked = { file -> + if (file.isFolder() && !file.isDisabled()) { + fileListViewModel.cancelDownloadFiles() + safeNavigate(SelectFolderFragmentDirections.fileListFragmentToFileListFragment(file.id, file.name)) } } } - lifecycleScope.launchWhenResumed { - val selectFolderActivity = requireActivity() as SelectFolderActivity - selectFolderActivity.showSaveButton() - val currentFolder = FileController.getFileById(folderId, userDrive) - val enable = folderId != saveExternalViewModel.disableSelectedFolder && - (currentFolder?.rights?.moveInto != false || currentFolder.rights?.newFile != false) - selectFolderActivity.enableSaveButton(enable) + lifecycleScope.launchWhenResumed { + with(requireActivity() as SelectFolderActivity) { + showSaveButton() + val currentFolderRights = FileController.getFileById(folderId, userDrive)?.rights ?: Rights() + val enable = folderId != saveExternalViewModel.disableSelectedFolderId + && (currentFolderRights.moveInto || currentFolderRights.newFile) + enableSaveButton(enable) + } } } private fun onBackPressed() { - if (folderId == ROOT_ID) { - requireActivity().finish() - } else Utils.ignoreCreateFolderBackStack(findNavController(), true) - + if (folderId == ROOT_ID) requireActivity().finish() else Utils.ignoreCreateFolderBackStack(findNavController(), true) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt index 049f40fd59..14afae6a27 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt @@ -217,11 +217,11 @@ object Utils { clipboard?.setPrimaryClip(ClipData.newPlainText(text, text)) } - fun Context.moveFileClicked(currentFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { + fun Context.moveFileClicked(currentFolderId: Int, selectFolderResultLauncher: ActivityResultLauncher) { val intent = Intent(this, SelectFolderActivity::class.java).apply { putExtra(SelectFolderActivity.USER_ID_TAG, AccountUtils.currentUserId) putExtra(SelectFolderActivity.USER_DRIVE_ID_TAG, AccountUtils.currentDriveId) - putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, currentFolder) + putExtra(SelectFolderActivity.DISABLE_SELECTED_FOLDER_TAG, currentFolderId) putExtra( SelectFolderActivity.CUSTOM_ARGS_TAG, bundleOf(SelectFolderActivity.BULK_OPERATION_CUSTOM_TAG to BulkOperationType.MOVE), diff --git a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt index 12ccc04808..7bf9506adb 100644 --- a/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt +++ b/app/src/main/java/com/infomaniak/drive/views/FileInfoActionsView.kt @@ -199,8 +199,8 @@ class FileInfoActionsView @JvmOverloads constructor( } availableOffline.setOnClickListener { availableOfflineSwitch.performClick() } moveFile.setOnClickListener { - val currentFolder = FileController.getParentFile(currentFile.id)?.id ?: -42 - onItemClickListener.moveFileClicked(ownerFragment.context, currentFolder, selectFolderResultLauncher) + val currentFolderId = FileController.getParentFile(currentFile.id)?.id ?: -42 + onItemClickListener.moveFileClicked(ownerFragment.context, currentFolderId, selectFolderResultLauncher) } duplicateFile.setOnClickListener { onItemClickListener.duplicateFileClicked(ownerFragment.requireContext(), currentFile) } renameFile.setOnClickListener { onItemClickListener.renameFileClicked(ownerFragment.requireContext(), currentFile) } @@ -429,8 +429,8 @@ class FileInfoActionsView @JvmOverloads constructor( } } - fun moveFileClicked(context: Context?, idFolder: Int, selectFolderResultLauncher: ActivityResultLauncher) { - context?.moveFileClicked(idFolder, selectFolderResultLauncher) + fun moveFileClicked(context: Context?, folderId: Int, selectFolderResultLauncher: ActivityResultLauncher) { + context?.moveFileClicked(folderId, selectFolderResultLauncher) } fun duplicateFileClicked(context: Context, currentFile: File) { diff --git a/app/src/main/res/navigation/select_folder.xml b/app/src/main/res/navigation/select_folder.xml index 1955ade458..bede50f3e8 100644 --- a/app/src/main/res/navigation/select_folder.xml +++ b/app/src/main/res/navigation/select_folder.xml @@ -18,7 +18,7 @@ Date: Fri, 18 Feb 2022 14:29:14 +0100 Subject: [PATCH 035/102] fix updateUploadCountNotification Signed-off-by: Abdourahamane BOINAIDI --- .../drive/data/services/UploadWorker.kt | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt index d81f439239..bcc07cc229 100644 --- a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt +++ b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt @@ -204,8 +204,8 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor currentUploadFile = this@initUpload applicationContext.cancelNotification(NotificationUtils.CURRENT_UPLOAD_ID) - setupCurrentUploadNotification(applicationContext, pendingCount) - + updateUploadCountNotification(this@initUpload, pendingCount) + try { if (uri.scheme.equals(ContentResolver.SCHEME_FILE)) { initUploadSchemeFile(uri) @@ -217,24 +217,6 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } - private fun UploadFile.handleException(exception: Exception, uri: Uri) { - when (exception) { - is SecurityException, is IllegalStateException, is IllegalArgumentException -> { - UploadFile.deleteIfExists(uri) - - if (exception is IllegalStateException) { - Sentry.withScope { scope -> - scope.setExtra("data", ApiController.gson.toJson(this)) - Sentry.captureMessage("The file is either partially downloaded or corrupted") - } - } else { - Sentry.captureException(exception) - } - } - else -> throw exception - } - } - private suspend fun UploadFile.initUploadSchemeFile(uri: Uri) { val cacheFile = uri.toFile().apply { if (!exists()) { @@ -287,6 +269,24 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } + private fun UploadFile.handleException(exception: Exception, uri: Uri) { + when (exception) { + is SecurityException, is IllegalStateException, is IllegalArgumentException -> { + UploadFile.deleteIfExists(uri) + + if (exception is IllegalStateException) { + Sentry.withScope { scope -> + scope.setExtra("data", ApiController.gson.toJson(this)) + Sentry.captureMessage("The file is either partially downloaded or corrupted") + } + } else { + Sentry.captureException(exception) + } + } + else -> throw exception + } + } + private suspend fun checkIfNeedReSync(syncSettings: SyncSettings?) { syncSettings?.let { checkLocalLastMedias(it) } if (UploadFile.getAllPendingUploadsCount() > 0) { @@ -295,14 +295,6 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } - private fun fileDescriptorSize(uri: Uri): Long? { - return try { - contentResolver.openFileDescriptor(uri, "r")?.use { it.statSize } - } catch (exception: Exception) { - null - } - } - private suspend fun checkLocalLastMedias(syncSettings: SyncSettings) = withContext(Dispatchers.IO) { val lastUploadDate = UploadFile.getLastDate(applicationContext).time - CHECK_LOCAL_LAST_MEDIAS_DELAY val selection = "( ${SyncUtils.DATE_TAKEN} >= ? " + @@ -358,6 +350,15 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor jobs.joinAll() } + private fun CoroutineScope.updateUploadCountNotification(uploadFile: UploadFile, pendingCount: Int) { + launch { + // We wait a little otherwise it is too fast and the notification may not be updated + delay(500) + ensureActive() + uploadFile.setupCurrentUploadNotification(applicationContext, pendingCount) + } + } + private fun CoroutineScope.getLocalLastMediasAsync( syncSettings: SyncSettings, contentUri: Uri, @@ -410,6 +411,14 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } + private fun fileDescriptorSize(uri: Uri): Long? { + return try { + contentResolver.openFileDescriptor(uri, "r")?.use { it.statSize } + } catch (exception: Exception) { + null + } + } + private fun syncMediaFolderFailure(exception: Throwable, contentUri: Uri, mediaFolder: MediaFolder) { // Catch Api>=29 for exception {Volume external_primary not found}, Adding logs to get more information if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && exception is IllegalArgumentException) { From 50d22a971c51485b159948f25f31b04ee472b3e0 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Fri, 18 Feb 2022 14:36:10 +0100 Subject: [PATCH 036/102] reduce sonar complexity Signed-off-by: Abdourahamane BOINAIDI --- .../drive/data/services/UploadWorker.kt | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt index bcc07cc229..a9c99cc949 100644 --- a/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt +++ b/app/src/main/java/com/infomaniak/drive/data/services/UploadWorker.kt @@ -19,6 +19,7 @@ package com.infomaniak.drive.data.services import android.content.ContentResolver import android.content.Context +import android.database.Cursor import android.net.Uri import android.os.Build import android.provider.MediaStore @@ -205,7 +206,7 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor applicationContext.cancelNotification(NotificationUtils.CURRENT_UPLOAD_ID) updateUploadCountNotification(this@initUpload, pendingCount) - + try { if (uri.scheme.equals(ContentResolver.SCHEME_FILE)) { initUploadSchemeFile(uri) @@ -375,35 +376,9 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor contentResolver.query(contentUri, null, selection, args, sortOrder) ?.use { cursor -> Log.d(TAG, "getLocalLastMediasAsync > from ${mediaFolder.name} ${cursor.count} found") + while (cursor.moveToNext()) { - val uri = cursor.uri(contentUri) - - val (fileCreatedAt, fileModifiedAt) = SyncUtils.getFileDates(cursor) - val fileName = SyncUtils.getFileName(cursor) - val fileSize = fileDescriptorSize(uri) ?: SyncUtils.getFileSize(cursor) - - Log.d(TAG, "getLocalLastMediasAsync > ${mediaFolder.name}/$fileName found") - - if (fileName != null && UploadFile.canUpload(uri, fileModifiedAt) && fileSize > 0) { - UploadFile.deleteIfExists(uri) - UploadFile( - uri = uri.toString(), - driveId = syncSettings.driveId, - fileCreatedAt = fileCreatedAt, - fileModifiedAt = fileModifiedAt, - fileName = fileName, - fileSize = fileSize, - remoteFolder = syncSettings.syncFolder, - userId = syncSettings.userId - ).apply { - createSubFolder(mediaFolder.name, syncSettings.createDatedSubFolders) - store() - } - - UploadFile.setAppSyncSettings(syncSettings.apply { - if (fileModifiedAt > lastSync) lastSync = fileModifiedAt - }) - } + localMediaFound(cursor, contentUri, mediaFolder, syncSettings) } } }.onFailure { exception -> @@ -411,6 +386,37 @@ class UploadWorker(appContext: Context, params: WorkerParameters) : CoroutineWor } } + private fun localMediaFound(cursor: Cursor, contentUri: Uri, mediaFolder: MediaFolder, syncSettings: SyncSettings) { + val uri = cursor.uri(contentUri) + + val (fileCreatedAt, fileModifiedAt) = SyncUtils.getFileDates(cursor) + val fileName = SyncUtils.getFileName(cursor) + val fileSize = fileDescriptorSize(uri) ?: SyncUtils.getFileSize(cursor) + + Log.d(TAG, "getLocalLastMediasAsync > ${mediaFolder.name}/$fileName found") + + if (fileName != null && UploadFile.canUpload(uri, fileModifiedAt) && fileSize > 0) { + UploadFile.deleteIfExists(uri) + UploadFile( + uri = uri.toString(), + driveId = syncSettings.driveId, + fileCreatedAt = fileCreatedAt, + fileModifiedAt = fileModifiedAt, + fileName = fileName, + fileSize = fileSize, + remoteFolder = syncSettings.syncFolder, + userId = syncSettings.userId + ).apply { + createSubFolder(mediaFolder.name, syncSettings.createDatedSubFolders) + store() + } + + UploadFile.setAppSyncSettings(syncSettings.apply { + if (fileModifiedAt > lastSync) lastSync = fileModifiedAt + }) + } + } + private fun fileDescriptorSize(uri: Uri): Long? { return try { contentResolver.openFileDescriptor(uri, "r")?.use { it.statSize } From e0f0139c9f35e3126d359bac0edb3504ddb1c7d8 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Mon, 21 Feb 2022 10:35:33 +0100 Subject: [PATCH 037/102] Replace file for sync offline conflict from upload task Close #576 Signed-off-by: Abdourahamane BOINAIDI --- app/src/main/java/com/infomaniak/drive/data/api/UploadTask.kt | 2 +- .../main/java/com/infomaniak/drive/data/models/UploadFile.kt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/api/UploadTask.kt b/app/src/main/java/com/infomaniak/drive/data/api/UploadTask.kt index a15ee6186d..2d9a0169f1 100644 --- a/app/src/main/java/com/infomaniak/drive/data/api/UploadTask.kt +++ b/app/src/main/java/com/infomaniak/drive/data/api/UploadTask.kt @@ -141,7 +141,7 @@ class UploadTask( val url = uploadUrl( chunkNumber = chunkNumber, - conflictOption = if (uploadFile.isSync() || uploadFile.isCloudStorage()) ConflictOption.REPLACE else ConflictOption.RENAME, + conflictOption = if (uploadFile.replaceOnConflict()) ConflictOption.REPLACE else ConflictOption.RENAME, currentChunkSize = count, totalChunks = totalChunks ) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/UploadFile.kt b/app/src/main/java/com/infomaniak/drive/data/models/UploadFile.kt index 50398bfeb9..76a6e43093 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/UploadFile.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/UploadFile.kt @@ -77,7 +77,9 @@ open class UploadFile( fun isSyncOffline() = type == Type.SYNC_OFFLINE.name - fun isCloudStorage() = type == Type.CLOUD_STORAGE.name + private fun isCloudStorage() = type == Type.CLOUD_STORAGE.name + + fun replaceOnConflict() = isSync() || isSyncOffline() || isCloudStorage() fun refreshIdentifier() { getRealmInstance().use { realm -> From ee85e2f6e13b23c7ae281d04c5265e0983503ba5 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Mon, 21 Feb 2022 13:17:53 +0100 Subject: [PATCH 038/102] refactor open with flags Signed-off-by: Abdourahamane BOINAIDI --- app/src/main/java/com/infomaniak/drive/utils/Utils.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt index 14afae6a27..9b13574709 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/Utils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/Utils.kt @@ -242,11 +242,9 @@ object Utils { val (cloudUri, uri) = file.getCloudAndFileUris(this, userDrive) return Intent().apply { action = Intent.ACTION_VIEW - addFlags( - Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION or - Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION - ) + flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION or + Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION setDataAndType(uri, contentResolver.getType(cloudUri)) } } From b0f111abdb30100475e3f56868bfd6612bd0d09b Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Mon, 21 Feb 2022 13:20:44 +0100 Subject: [PATCH 039/102] On open with an offline file, share it's file uri instead of content uri Close #573 Signed-off-by: Abdourahamane BOINAIDI --- app/src/main/java/com/infomaniak/drive/data/models/File.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/drive/data/models/File.kt b/app/src/main/java/com/infomaniak/drive/data/models/File.kt index 2948ff38d9..74b54e905f 100644 --- a/app/src/main/java/com/infomaniak/drive/data/models/File.kt +++ b/app/src/main/java/com/infomaniak/drive/data/models/File.kt @@ -21,7 +21,7 @@ import android.content.Context import android.net.Uri import android.os.Parcelable import android.webkit.MimeTypeMap -import androidx.core.content.FileProvider +import androidx.core.net.toUri import androidx.work.WorkInfo import androidx.work.WorkManager import com.google.gson.annotations.SerializedName @@ -438,7 +438,8 @@ open class File( val offlineFile = getOfflineFile(context, userDrive.userId) return cloudUri to if (isOffline && offlineFile != null) { - FileProvider.getUriForFile(context, context.getString(R.string.FILE_AUTHORITY), offlineFile) + // We use the uri with scheme file because some apps don't support modifications from a content uri + offlineFile.toUri() } else cloudUri } From 4e94ebbae2b89d047954294cf7f80bf248cd3451 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 25 Jan 2022 17:53:26 +0100 Subject: [PATCH 040/102] Added Android CI --- .github/workflows/android.yml | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/android.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000000..725541b333 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,64 @@ +name: Android CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master, android-ci ] + +jobs: + + build: + + runs-on: self-hosted + + env: + ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" + ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} + INVITE_USER_NAME: ${{ secrets.INVITE_USER_NAME }} + NEW_USER_NAME: ${{ secrets.NEW_USER_NAME }} + NEW_USER_PASSWORD: ${{ secrets.NEW_USER_PASSWORD }} + + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.9.1 + with: + access_token: ${{ github.token }} + + - name: Checkout + uses: actions/checkout@v2 + with: + token: ${{ secrets.MY_REPO_PAT }} + submodules: recursive + + - name: set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: 11 + distribution: 'zulu' + cache: gradle + + - name: Create test env + run: | + touch $ENV_PATH + echo "object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = 140946; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = 1048949; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH + + # Setup Gradle and Run tests + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build project + run: ./gradlew assembleStandard --stacktrace + - name: Run Unit tests + run: ./gradlew testDebugUnitTest --stacktrace + + - name: Run instrumentation tests + uses: ReactiveCircus/android-emulator-runner@v2.22.0 + with: + api-level: 31 + arch: x86_64 + profile: pixel_4 + avd-name: test + emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace + From 58828482fe8399a4a7ff0499950327fafa10f563 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Feb 2022 16:43:34 +0100 Subject: [PATCH 041/102] add debug option --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 725541b333..7f5ae704e6 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -60,5 +60,5 @@ jobs: avd-name: test emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace + script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace --debug From 891d033f3d302b14dafa321bec5eab97388aa6f1 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Feb 2022 18:04:52 +0100 Subject: [PATCH 042/102] add emulator cache + setup an other emulator --- .github/workflows/android.yml | 51 +++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7f5ae704e6..c73c1d5ba2 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -11,6 +11,9 @@ jobs: build: runs-on: self-hosted + strategy: + matrix: + api-level: [29] env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" @@ -31,12 +34,39 @@ jobs: token: ${{ secrets.MY_REPO_PAT }} submodules: recursive - - name: set up JDK 11 - uses: actions/setup-java@v2 + - name: Gradle cache + uses: actions/cache@v2 with: - java-version: 11 - distribution: 'zulu' - cache: gradle + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} + + - name: AVD cache + uses: actions/cache@v2 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ matrix.api-level }} + + - name: create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: false + script: echo "Generated AVD snapshot for caching." + +# - name: set up JDK 11 +# uses: actions/setup-java@v2 +# with: +# java-version: 11 +# distribution: 'zulu' +# cache: gradle - name: Create test env run: | @@ -46,19 +76,18 @@ jobs: # Setup Gradle and Run tests - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build project - run: ./gradlew assembleStandard --stacktrace - name: Run Unit tests run: ./gradlew testDebugUnitTest --stacktrace - name: Run instrumentation tests uses: ReactiveCircus/android-emulator-runner@v2.22.0 with: - api-level: 31 + api-level: ${{ matrix.api-level }} arch: x86_64 - profile: pixel_4 - avd-name: test + profile: Nexus 6 + avd-name: avd test + force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace --debug + script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace From 736ae3df068c77d13f097cdf1d74ca68960bffb4 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Feb 2022 18:10:44 +0100 Subject: [PATCH 043/102] Setup java 11 --- .github/workflows/android.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index c73c1d5ba2..7d4122efa3 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -61,12 +61,12 @@ jobs: disable-animations: false script: echo "Generated AVD snapshot for caching." -# - name: set up JDK 11 -# uses: actions/setup-java@v2 -# with: -# java-version: 11 -# distribution: 'zulu' -# cache: gradle + - name: set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: 11 + distribution: 'zulu' + cache: gradle - name: Create test env run: | From e56070ddd6dd54868112f8acdfa4141d4b2bc454 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Feb 2022 18:30:08 +0100 Subject: [PATCH 044/102] update emulator options --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7d4122efa3..dc3fbcda9e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -87,7 +87,7 @@ jobs: profile: Nexus 6 avd-name: avd test force-avd-creation: false - emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace From 31ef4bc1d5921820719e13ffb6369229eafa746d Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 12:52:57 +0100 Subject: [PATCH 045/102] update api-level --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index dc3fbcda9e..876f08e9dd 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,7 +13,7 @@ jobs: runs-on: self-hosted strategy: matrix: - api-level: [29] + api-level: [31] env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" From 5c16dccadf2e5db5e2292d888994e3524fc3a158 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 13:00:15 +0100 Subject: [PATCH 046/102] set api-level to 30 --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 876f08e9dd..eefceb25c8 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,7 +13,7 @@ jobs: runs-on: self-hosted strategy: matrix: - api-level: [31] + api-level: [30] env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" From eb4194fa0dd04d7fdd791a662114f6d7a90d2202 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 13:16:07 +0100 Subject: [PATCH 047/102] Set api-level to 29 --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index eefceb25c8..dc3fbcda9e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -13,7 +13,7 @@ jobs: runs-on: self-hosted strategy: matrix: - api-level: [30] + api-level: [29] env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" From 262f10146d2d20d78075a479ca5ed811061e4771 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 17:22:31 +0100 Subject: [PATCH 048/102] use pixel 4 emulator --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index dc3fbcda9e..41cec01f91 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -84,7 +84,7 @@ jobs: with: api-level: ${{ matrix.api-level }} arch: x86_64 - profile: Nexus 6 + profile: Pixel_4 avd-name: avd test force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From 64d7ad41a10844b94e51e8ff3e27fc9186418cc9 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 19:33:25 +0100 Subject: [PATCH 049/102] update ci --- .github/workflows/android.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 41cec01f91..1e78ec72e5 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -4,7 +4,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master, android-ci ] + branches: [ master ] jobs: @@ -28,7 +28,7 @@ jobs: with: access_token: ${{ github.token }} - - name: Checkout + - name: Checkout the code uses: actions/checkout@v2 with: token: ${{ secrets.MY_REPO_PAT }} @@ -83,11 +83,11 @@ jobs: uses: ReactiveCircus/android-emulator-runner@v2.22.0 with: api-level: ${{ matrix.api-level }} - arch: x86_64 - profile: Pixel_4 - avd-name: avd test + #arch: x86_64 + #profile: Pixel_4 + #avd-name: avd test force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew clean :app:connectedStandardDebugAndroidTest --stacktrace + script: ./gradlew :app:connectedStandardDebugAndroidTest --stacktrace From 37e01662a19482e8750cf187d9132f9d24008701 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 19:37:19 +0100 Subject: [PATCH 050/102] Update android ci pull request --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 1e78ec72e5..ff9dff3f3c 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -4,7 +4,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + branches: [ master, android-ci ] jobs: From e5a1dbea94faf03430f9f05069b111b0387b7f7b Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Feb 2022 20:11:37 +0100 Subject: [PATCH 051/102] Update run instrumentation tests --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ff9dff3f3c..0c61182cef 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -89,5 +89,5 @@ jobs: force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew :app:connectedStandardDebugAndroidTest --stacktrace + script: ./gradlew app:connectedAndroidTest --stacktrace From 9f7d183a550c2529db58469acf415e38b65fcf3d Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 10:41:03 +0100 Subject: [PATCH 052/102] Add google apis target --- .github/workflows/android.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0c61182cef..29480e3cda 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -14,6 +14,7 @@ jobs: strategy: matrix: api-level: [29] + target: [google_apis] env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" @@ -56,6 +57,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: false @@ -83,11 +85,12 @@ jobs: uses: ReactiveCircus/android-emulator-runner@v2.22.0 with: api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} #arch: x86_64 #profile: Pixel_4 #avd-name: avd test force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - script: ./gradlew app:connectedAndroidTest --stacktrace + script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 72367d831ad5aa8edb37c13a11fd659d6e9cfde5 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 11:00:06 +0100 Subject: [PATCH 053/102] Add github properties file --- .github/workflows/android.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 29480e3cda..c571b40036 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -43,6 +43,9 @@ jobs: ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} + - name: Copy gradle properties file + run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties + - name: AVD cache uses: actions/cache@v2 id: avd-cache @@ -78,6 +81,7 @@ jobs: # Setup Gradle and Run tests - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Run Unit tests run: ./gradlew testDebugUnitTest --stacktrace From 01900849e655b25aaa3b96ff09c503b404e3612c Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 11:04:13 +0100 Subject: [PATCH 054/102] remove github properties --- .github/workflows/android.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index c571b40036..8757e947e4 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -42,10 +42,7 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} - - - name: Copy gradle properties file - run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - + - name: AVD cache uses: actions/cache@v2 id: avd-cache From 196a2df6cf34c6fe8f5f63ccd08734dfcd237f86 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 14:55:48 +0100 Subject: [PATCH 055/102] update emulator options --- .github/workflows/android.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8757e947e4..cee8d10000 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -58,6 +58,7 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} + sdcard-path-or-size: 100M force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: false @@ -90,8 +91,10 @@ jobs: #arch: x86_64 #profile: Pixel_4 #avd-name: avd test + sdcard-path-or-size: 100M force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From bf4bc9727886864dda023abdaeb188e0293db2f7 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 15:06:07 +0100 Subject: [PATCH 056/102] update run instrumentation tests script --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index cee8d10000..2263497da4 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -96,5 +96,5 @@ jobs: #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 disable-animations: true - script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace + script: ./gradlew connectedCheck --stacktrace From ea3bc2bed52211ff4bdafe58e0120966a9151431 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 18:38:26 +0100 Subject: [PATCH 057/102] Update run tests --- .github/workflows/android.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 2263497da4..9dbceeb348 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -93,8 +93,8 @@ jobs: #avd-name: avd test sdcard-path-or-size: 100M force-avd-creation: false - #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + #emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 disable-animations: true - script: ./gradlew connectedCheck --stacktrace + script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From c5ea5e800400c60582e91aa7a89ea657de3c6a0f Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 20:12:36 +0100 Subject: [PATCH 058/102] update ci --- .github/workflows/android.yml | 40 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 9dbceeb348..3c6a5874e6 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -5,6 +5,10 @@ on: branches: [ master ] pull_request: branches: [ master, android-ci ] + +env: + # Increment this to manually invalidate the cache. + CACHE_VERSION: 1 jobs: @@ -43,22 +47,41 @@ jobs: ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} - - name: AVD cache - uses: actions/cache@v2 +# - name: AVD cache +# uses: actions/cache@v2 +# id: avd-cache +# with: +# path: | +# ~/.android/avd/* +# ~/.android/adb* +# key: avd-${{ matrix.api-level }} + + + - name: Get AVD info + uses: ./.github/actions/get-avd-info + id: avd-info + with: + api-level: ${{ matrix.api-level }} + + # Retrieve the cached emulator snapshot. + - uses: actions/cache@v2 id: avd-cache with: path: | ~/.android/avd/* ~/.android/adb* - key: avd-${{ matrix.api-level }} + key: ${{ runner.os }}-avd-${{ env.CACHE_VERSION }}-${{ steps.avd-info.outputs.arch }}-${{ steps.avd-info.outputs.target }}-${{ matrix.api-level }} - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} - target: ${{ matrix.target }} - sdcard-path-or-size: 100M + arch: ${{ steps.avd-info.outputs.arch }} + target: ${{ steps.avd-info.outputs.target }} +# target: ${{ matrix.target }} +# sdcard-path-or-size: 100M + ram-size: 4096M force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: false @@ -87,11 +110,14 @@ jobs: uses: ReactiveCircus/android-emulator-runner@v2.22.0 with: api-level: ${{ matrix.api-level }} - target: ${{ matrix.target }} + arch: ${{ steps.avd-info.outputs.arch }} + target: ${{ steps.avd-info.outputs.target }} +# target: ${{ matrix.target }} #arch: x86_64 #profile: Pixel_4 #avd-name: avd test - sdcard-path-or-size: 100M + ram-size: 4096M +# sdcard-path-or-size: 100M force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none #emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 From dd4e714e98aa4c399901f3a672eb61e709702385 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 16 Feb 2022 20:17:59 +0100 Subject: [PATCH 059/102] update ci --- .github/workflows/android.yml | 36 ++++++----------------------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 3c6a5874e6..fa4fc44963 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -5,14 +5,10 @@ on: branches: [ master ] pull_request: branches: [ master, android-ci ] - -env: - # Increment this to manually invalidate the cache. - CACHE_VERSION: 1 jobs: - build: + instrumentation-tests: runs-on: self-hosted strategy: @@ -47,39 +43,21 @@ jobs: ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} -# - name: AVD cache -# uses: actions/cache@v2 -# id: avd-cache -# with: -# path: | -# ~/.android/avd/* -# ~/.android/adb* -# key: avd-${{ matrix.api-level }} - - - - name: Get AVD info - uses: ./.github/actions/get-avd-info - id: avd-info - with: - api-level: ${{ matrix.api-level }} - - # Retrieve the cached emulator snapshot. - - uses: actions/cache@v2 + - name: AVD cache + uses: actions/cache@v2 id: avd-cache with: path: | ~/.android/avd/* ~/.android/adb* - key: ${{ runner.os }}-avd-${{ env.CACHE_VERSION }}-${{ steps.avd-info.outputs.arch }}-${{ steps.avd-info.outputs.target }}-${{ matrix.api-level }} + key: avd-${{ matrix.api-level }} - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ matrix.api-level }} - arch: ${{ steps.avd-info.outputs.arch }} - target: ${{ steps.avd-info.outputs.target }} -# target: ${{ matrix.target }} + target: ${{ matrix.target }} # sdcard-path-or-size: 100M ram-size: 4096M force-avd-creation: false @@ -110,9 +88,7 @@ jobs: uses: ReactiveCircus/android-emulator-runner@v2.22.0 with: api-level: ${{ matrix.api-level }} - arch: ${{ steps.avd-info.outputs.arch }} - target: ${{ steps.avd-info.outputs.target }} -# target: ${{ matrix.target }} + target: ${{ matrix.target }} #arch: x86_64 #profile: Pixel_4 #avd-name: avd test From 11f45ce096f8ecf25d574bf1b46263a68a4c252b Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 09:53:41 +0100 Subject: [PATCH 060/102] update android ci --- .github/workflows/android.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index fa4fc44963..93612085f0 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -58,7 +58,6 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} -# sdcard-path-or-size: 100M ram-size: 4096M force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -75,7 +74,7 @@ jobs: - name: Create test env run: | touch $ENV_PATH - echo "object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = 140946; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = 1048949; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH + echo "package com.infomaniak.drive.utils; object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = 140946; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = 1048949; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH # Setup Gradle and Run tests - name: Grant execute permission for gradlew @@ -91,12 +90,9 @@ jobs: target: ${{ matrix.target }} #arch: x86_64 #profile: Pixel_4 - #avd-name: avd test ram-size: 4096M -# sdcard-path-or-size: 100M force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - #emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -skin 500x833 disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From d13436ac6c2975c4dc236ecb237a11c1b1f6f017 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 11:00:01 +0100 Subject: [PATCH 061/102] Update test Env --- .github/workflows/android.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 93612085f0..43595a34e6 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -19,7 +19,9 @@ jobs: env: ENV_PATH: "app/src/androidTest/java/com/infomaniak/drive/utils/Env.kt" ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} + DRIVE_ID: ${{ secrets.DRIVE_ID }} INVITE_USER_NAME: ${{ secrets.INVITE_USER_NAME }} + NEW_USER_ID: ${{ secrets.NEW_USER_ID }} NEW_USER_NAME: ${{ secrets.NEW_USER_NAME }} NEW_USER_PASSWORD: ${{ secrets.NEW_USER_PASSWORD }} @@ -74,7 +76,7 @@ jobs: - name: Create test env run: | touch $ENV_PATH - echo "package com.infomaniak.drive.utils; object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = 140946; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = 1048949; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH + echo "package com.infomaniak.drive.utils; object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = $DRIVE_ID; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = $NEW_USER_ID; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH # Setup Gradle and Run tests - name: Grant execute permission for gradlew From 2ee60e58ed7a7690c0c434e39dbf07579f72f196 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 12:00:48 +0100 Subject: [PATCH 062/102] Authorize emulator view with gpu --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 43595a34e6..81d0addbba 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -62,7 +62,7 @@ jobs: target: ${{ matrix.target }} ram-size: 4096M force-avd-creation: false - emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -94,7 +94,7 @@ jobs: #profile: Pixel_4 ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From e7ddf83f9154146f31a2ea01d8842cb70d8dcb03 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 15:04:35 +0100 Subject: [PATCH 063/102] remove jdk setup --- .github/workflows/android.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 81d0addbba..29fee7d359 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -60,18 +60,18 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} - ram-size: 4096M - force-avd-creation: false +# ram-size: 4096M +# force-avd-creation: false #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: false +# disable-animations: false script: echo "Generated AVD snapshot for caching." - - name: set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: 11 - distribution: 'zulu' - cache: gradle +# - name: set up JDK 11 +# uses: actions/setup-java@v2 +# with: +# java-version: 11 +# distribution: 'zulu' +# cache: gradle - name: Create test env run: | @@ -92,9 +92,9 @@ jobs: target: ${{ matrix.target }} #arch: x86_64 #profile: Pixel_4 - ram-size: 4096M - force-avd-creation: false +# ram-size: 4096M +# force-avd-creation: false #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: true +# disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From e4fb82353279bdb4f1c4b9749b6443c311718b58 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 15:29:19 +0100 Subject: [PATCH 064/102] enable jdk setup --- .github/workflows/android.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 29fee7d359..8d2850a1a2 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -66,12 +66,12 @@ jobs: # disable-animations: false script: echo "Generated AVD snapshot for caching." -# - name: set up JDK 11 -# uses: actions/setup-java@v2 -# with: -# java-version: 11 -# distribution: 'zulu' -# cache: gradle + - name: set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: 11 + distribution: 'zulu' + cache: gradle - name: Create test env run: | From 0bfb3ccc7d20250c128b4dd8980db631623b6237 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 18:10:27 +0100 Subject: [PATCH 065/102] use pixel 4 --- .github/workflows/android.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8d2850a1a2..825e173fa1 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -60,18 +60,20 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} + arch: x86_64 + profile: Pixel_4 # ram-size: 4096M # force-avd-creation: false #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: false script: echo "Generated AVD snapshot for caching." - - name: set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: 11 - distribution: 'zulu' - cache: gradle +# - name: set up JDK 11 +# uses: actions/setup-java@v2 +# with: +# java-version: 11 +# distribution: 'zulu' +# cache: gradle - name: Create test env run: | @@ -90,8 +92,8 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} - #arch: x86_64 - #profile: Pixel_4 + arch: x86_64 + profile: Pixel_4 # ram-size: 4096M # force-avd-creation: false #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From fb860bf6313c780140d05a3ac6c0e16cd393c06f Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 18:16:04 +0100 Subject: [PATCH 066/102] remove pixel 4 --- .github/workflows/android.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 825e173fa1..832f6baa41 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -61,7 +61,6 @@ jobs: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} arch: x86_64 - profile: Pixel_4 # ram-size: 4096M # force-avd-creation: false #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none @@ -93,7 +92,7 @@ jobs: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} arch: x86_64 - profile: Pixel_4 +# profile: Pixel_4 # ram-size: 4096M # force-avd-creation: false #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none From ad99139fcaed125890b60e125ad712c33a821437 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 18:44:01 +0100 Subject: [PATCH 067/102] new avd name --- .github/workflows/android.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 832f6baa41..5fb1be9fa5 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -61,8 +61,9 @@ jobs: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} arch: x86_64 + avd-name: kdrive-test # ram-size: 4096M -# force-avd-creation: false + force-avd-creation: false #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -92,9 +93,10 @@ jobs: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} arch: x86_64 + avd-name: kdrive-test # profile: Pixel_4 # ram-size: 4096M -# force-avd-creation: false + force-avd-creation: false #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 239a6f641b9b169719775892df94ec8745bd71b0 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Thu, 17 Feb 2022 18:55:33 +0100 Subject: [PATCH 068/102] enable emulator window --- .github/workflows/android.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5fb1be9fa5..17f14fe8c4 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -64,6 +64,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -97,6 +98,7 @@ jobs: # profile: Pixel_4 # ram-size: 4096M force-avd-creation: false + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From b6979a71bee06251de012938a32b0835601d7744 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 15:00:37 +0100 Subject: [PATCH 069/102] add pixel 4 --- .github/workflows/android.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 17f14fe8c4..e85136fa3a 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -60,6 +60,7 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} + profile: Pixel 4 arch: x86_64 avd-name: kdrive-test # ram-size: 4096M @@ -93,9 +94,9 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} + profile: Pixel 4 arch: x86_64 avd-name: kdrive-test -# profile: Pixel_4 # ram-size: 4096M force-avd-creation: false emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none From 42fc1c1585cf824b5b5fc9de13056737b10b8deb Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 15:10:50 +0100 Subject: [PATCH 070/102] display size --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index e85136fa3a..5d14b90790 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -99,7 +99,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 2220x1080 #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 6d030a1c7c1d06938121b2ea0ab36c27791f5b36 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 15:24:39 +0100 Subject: [PATCH 071/102] define skin --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5d14b90790..f64ae1c5cf 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -65,7 +65,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin WXGA800 #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -99,7 +99,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 2220x1080 + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin WXGA800 #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From c8d2c0f0ebd6786e590826a75c26bfe8292ed2f1 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 15:29:59 +0100 Subject: [PATCH 072/102] =?UTF-8?q?skin=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f64ae1c5cf..d53d3c0c5b 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -65,8 +65,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin WXGA800 - #emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 # disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -99,7 +98,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin WXGA800 + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 4365d6c9d54c9e675d249ff054977bbfd8a7b35d Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 15:45:40 +0100 Subject: [PATCH 073/102] ci without window and gpu --- .github/workflows/android.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d53d3c0c5b..616019ad89 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -65,7 +65,7 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 # disable-animations: false script: echo "Generated AVD snapshot for caching." @@ -98,8 +98,8 @@ jobs: avd-name: kdrive-test # ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 - #emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none +# emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 # disable-animations: true script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 1504ee237231baf93dfe7bbf2b1e20b4d0fbcf9a Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 18 Feb 2022 17:17:11 +0100 Subject: [PATCH 074/102] change emulator window size --- .github/workflows/android.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 616019ad89..efa2abb56c 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -63,10 +63,8 @@ jobs: profile: Pixel 4 arch: x86_64 avd-name: kdrive-test -# ram-size: 4096M force-avd-creation: false - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 -# disable-animations: false + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 540x1110 script: echo "Generated AVD snapshot for caching." # - name: set up JDK 11 @@ -96,10 +94,8 @@ jobs: profile: Pixel 4 arch: x86_64 avd-name: kdrive-test -# ram-size: 4096M force-avd-creation: false -# emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 1080x2220 - emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 -# disable-animations: true + emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 540x1110 +# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 2ce81586353fb4f85ee0c235735116e737402260 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 21 Feb 2022 18:49:52 +0100 Subject: [PATCH 075/102] Hide emulator window --- .github/workflows/android.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index efa2abb56c..d51d523ee2 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -64,7 +64,7 @@ jobs: arch: x86_64 avd-name: kdrive-test force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 540x1110 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 540x1110 script: echo "Generated AVD snapshot for caching." # - name: set up JDK 11 @@ -95,7 +95,7 @@ jobs: arch: x86_64 avd-name: kdrive-test force-avd-creation: false - emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 540x1110 -# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 1080x2220 +# emulator-options: -no-snapshot-save -noaudio -no-boot-anim -camera-back none -skin 540x1110 + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -skin 540x1110 script: ./gradlew app:connectedStandardDebugAndroidTest --stacktrace From 1bb7d28751a109efccd11577988b23d8cf846f12 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 17 Jan 2022 11:58:52 +0100 Subject: [PATCH 076/102] Fix first Ui test Fix create then delete folder ui test --- .../com/infomaniak/drive/ui/FileItemUiTest.kt | 2 ++ .../com/infomaniak/drive/ui/FileListUiTest.kt | 13 +++++---- .../com/infomaniak/drive/utils/UiTestUtils.kt | 28 +++++++++++++++---- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt index c6ffdb0cde..3e3de0d63e 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt @@ -47,7 +47,9 @@ class FileItemUiTest { val randomFolderName = "UI-Test-${UUID.randomUUID()}" val fileRecyclerView = UiScrollable(UiSelector().resourceId(getViewIdentifier("fileRecyclerView"))) + // Create the folder then returns to main view UiTestUtils.createPrivateFolder(randomFolderName) + // Go to fileList view UiTestUtils.openFileShareDetails(fileRecyclerView, randomFolderName) device.apply { diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt index a7223ca246..acfd0eff5d 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt @@ -21,9 +21,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import com.infomaniak.drive.utils.UiTestUtils +import com.infomaniak.drive.utils.UiTestUtils.deleteFile import com.infomaniak.drive.utils.UiTestUtils.device +import com.infomaniak.drive.utils.UiTestUtils.findFileInList import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier import com.infomaniak.drive.utils.UiTestUtils.startApp +import junit.framework.Assert.assertNotNull +import junit.framework.Assert.assertNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -42,16 +46,15 @@ class FileListUiTest { } @Test - fun testCreateFolder() { + fun testCreateAndDeleteFolder() { val fileRecyclerView = UiScrollable(UiSelector().resourceId(getViewIdentifier("fileRecyclerView"))) - val initialFileNumber = fileRecyclerView.childCount val randomFolderName = "UI-Test-${UUID.randomUUID()}" UiTestUtils.createPrivateFolder(randomFolderName) device.waitForWindowUpdate(null, 5000) - assert(fileRecyclerView.childCount == initialFileNumber + 1) + assertNotNull("File must be found", findFileInList(fileRecyclerView, randomFolderName)) - UiTestUtils.deleteFile(fileRecyclerView, randomFolderName) - assert(fileRecyclerView.childCount == initialFileNumber) + deleteFile(fileRecyclerView, randomFolderName) + assertNull("File must not be found", findFileInList(fileRecyclerView, randomFolderName)) } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index 2285acb06b..0b2df15010 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -65,20 +65,29 @@ object UiTestUtils { UiCollection(UiSelector().resourceId(getViewIdentifier("createFolderLayout"))).apply { getChildByInstance(UiSelector().resourceId(getViewIdentifier("folderNameValueInput")), 0).text = folderName + val permissionsRecyclerView = UiScrollable(UiSelector().resourceId(getViewIdentifier("permissionsRecyclerView"))) + permissionsRecyclerView.getChildByText( + UiSelector().resourceId(getViewIdentifier("permissionCard")), + context.getString(R.string.createFolderMeOnly) + ).apply { + permissionsRecyclerView.scrollIntoView(this) + this.click() + } getChildByText( UiSelector().resourceId(getViewIdentifier("createFolderButton")), context.getString(R.string.buttonCreateFolder) ).clickAndWaitForNewWindow() } - - device.pressBack() } fun deleteFile(fileRecyclerView: UiScrollable, fileName: String) { (fileRecyclerView.getChildByText(UiSelector().resourceId(getViewIdentifier("fileCardView")), fileName)).apply { fileRecyclerView.scrollIntoView(this) - swipeLeft(3) - getChild((UiSelector().resourceId(getViewIdentifier("deleteButton")))).clickAndWaitForNewWindow() + val fileInfoMenu = this.getChild(UiSelector().resourceId(getViewIdentifier("menuButton"))) + fileInfoMenu.click() + val menuView = UiScrollable(UiSelector().resourceId(getViewIdentifier("scrollView"))) + menuView.scrollForward() + menuView.getChild(UiSelector().resourceId(getViewIdentifier("deleteFile"))).click() } device.findObject(UiSelector().text(context.getString(R.string.buttonMove))).clickAndWaitForNewWindow() } @@ -89,10 +98,17 @@ object UiTestUtils { swipeLeft(3) getChild((UiSelector().resourceId(getViewIdentifier("menuButton")))).clickAndWaitForNewWindow() } + getDeviceViewById("fileRights")?.clickAndWaitForNewWindow() } - fun getDeviceViewById(id: String): UiObject? { - return device.findObject(UiSelector().resourceId(getViewIdentifier(id))) + fun getDeviceViewById(id: String): UiObject? = device.findObject(UiSelector().resourceId(getViewIdentifier(id))) + + fun findFileInList(fileRecyclerView: UiScrollable, fileName: String): UiObject? { + return try { + fileRecyclerView.getChildByText(UiSelector().resourceId(getViewIdentifier("fileCardView")), fileName) + } catch (exception: UiObjectNotFoundException) { + null + } } } \ No newline at end of file From 376be15516f3ee3095a6220b9d85ca13a0ae2464 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 18 Jan 2022 11:04:15 +0100 Subject: [PATCH 077/102] fix Ui test in progress Fix the addUser Test and changed getDeviceViewById signature to delete nullability because UiAutomator throws exception instead of returning null --- .../com/infomaniak/drive/ui/FileItemUiTest.kt | 10 ++-- .../com/infomaniak/drive/ui/FileListUiTest.kt | 6 +-- .../com/infomaniak/drive/ui/MenuUiTest.kt | 51 ++++++++++--------- .../com/infomaniak/drive/utils/UiTestUtils.kt | 31 +++++++---- 4 files changed, 55 insertions(+), 43 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt index 3e3de0d63e..180a7f86ae 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt @@ -21,6 +21,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import com.infomaniak.drive.utils.UiTestUtils +import com.infomaniak.drive.utils.UiTestUtils.createPublicShareLink +import com.infomaniak.drive.utils.UiTestUtils.deleteFile import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier @@ -54,10 +56,10 @@ class FileItemUiTest { device.apply { findObject(UiSelector().resourceId(getViewIdentifier("shareLinkSwitch"))).clickAndWaitForNewWindow() - findObject(UiSelector().resourceId(getViewIdentifier("urlValue"))).let { - assert(it.exists()) - assert(it.text.isNotEmpty()) - } + createPublicShareLink(UiScrollable(UiSelector().resourceId(getViewIdentifier("permissionsRecyclerView")))) + pressBack() + findObject(UiSelector().resourceId(getViewIdentifier("closeButton"))).clickAndWaitForNewWindow() } + deleteFile(fileRecyclerView, randomFolderName) } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt index acfd0eff5d..de30bc4c30 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt @@ -26,8 +26,8 @@ import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.findFileInList import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier import com.infomaniak.drive.utils.UiTestUtils.startApp -import junit.framework.Assert.assertNotNull -import junit.framework.Assert.assertNull +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -42,7 +42,7 @@ class FileListUiTest { @Before fun init() { startApp() - UiTestUtils.getDeviceViewById("fileListFragment")?.click() + UiTestUtils.getDeviceViewById("fileListFragment").click() } @Test diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index a0e842841c..a0dd469c00 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -23,6 +23,7 @@ import android.widget.EditText import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.matcher.ViewMatchers import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiObjectNotFoundException import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import com.infomaniak.drive.R @@ -34,7 +35,6 @@ import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import org.hamcrest.CoreMatchers import org.junit.Before import org.junit.Test -import java.lang.Thread.sleep class MenuUiTest { @Before @@ -50,37 +50,38 @@ class MenuUiTest { } context.startActivity(intent) device.wait(Until.hasObject(By.pkg(UiTestUtils.APP_PACKAGE).depth(0)), UiTestUtils.LAUNCH_TIMEOUT) - getDeviceViewById("menuFragment")?.clickAndWaitForNewWindow() + getDeviceViewById("menuFragment").clickAndWaitForNewWindow() } @Test fun testAddUser() { - getDeviceViewById("changeUser")?.clickAndWaitForNewWindow() - getDeviceViewById("addUser")?.clickAndWaitForNewWindow() - getDeviceViewById("nextButton")?.click() - getDeviceViewById("nextButton")?.click() - getDeviceViewById("connectButton")?.clickAndWaitForNewWindow() + getDeviceViewById("changeUserIcon").clickAndWaitForNewWindow() + getDeviceViewById("addUser").clickAndWaitForNewWindow() + getDeviceViewById("nextButton").click() + getDeviceViewById("nextButton").click() + getDeviceViewById("connectButton").clickAndWaitForNewWindow() - // Username - device.findObject(UiSelector().instance(0).className(EditText::class.java)).text = Env.NEW_USER_NAME + with(device) { + // Username + findObject(UiSelector().instance(0).className(EditText::class.java)).text = Env.NEW_USER_NAME - // Password - device.findObject(UiSelector().text("Mot de passe")).text = Env.NEW_USER_PASSWORD - device.findObject(UiSelector().text("CONNEXION")).clickAndWaitForNewWindow() + // Password + findObject(UiSelector().instance(1).className(EditText::class.java)).text = Env.NEW_USER_PASSWORD - sleep(6000) + // Save button + try { + findObject(UiSelector().text("CONNECTION")).clickAndWaitForNewWindow(6000) + } catch (exception: UiObjectNotFoundException) { + findObject(UiSelector().text("CONNEXION")).clickAndWaitForNewWindow(6000) + } - assert(AccountUtils.currentUserId == Env.NEW_USER_ID) - getDeviceViewById("menuFragment")?.clickAndWaitForNewWindow() - // Cheat to scroll to bottom of screen - device.swipe( - device.displayWidth * 3 / 4, - device.displayHeight * 9 / 10, - device.displayWidth * 3 / 4, - device.displayHeight * 1 / 10, - 10 - ) - getDeviceViewById("logout")?.clickAndWaitForNewWindow() - device.findObject(UiSelector().text(UiTestUtils.context.getString(R.string.buttonConfirm))).clickAndWaitForNewWindow() + assert(AccountUtils.currentUserId == Env.NEW_USER_ID) { "User Id should be ${Env.NEW_USER_ID} but is ${AccountUtils.currentUserId}" } + getDeviceViewById("menuFragment").clickAndWaitForNewWindow(2000) + + // Cheat to scroll down because nestedScrollView doesn't want to scroll + swipe(displayWidth / 4, displayHeight - 20, displayWidth / 4, displayHeight / 4, 5) + getDeviceViewById("logout").clickAndWaitForNewWindow() + findObject(UiSelector().text(UiTestUtils.context.getString(R.string.buttonConfirm))).clickAndWaitForNewWindow() + } } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index 0b2df15010..98f7ac6f38 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -52,7 +52,7 @@ object UiTestUtils { } fun createPrivateFolder(folderName: String) { - getDeviceViewById("mainFab")?.clickAndWaitForNewWindow() + getDeviceViewById("mainFab").clickAndWaitForNewWindow() UiCollection(UiSelector().resourceId(getViewIdentifier("addFileBottomSheetLayout"))).getChildByText( UiSelector().resourceId(getViewIdentifier("folderCreateText")), @@ -83,11 +83,11 @@ object UiTestUtils { fun deleteFile(fileRecyclerView: UiScrollable, fileName: String) { (fileRecyclerView.getChildByText(UiSelector().resourceId(getViewIdentifier("fileCardView")), fileName)).apply { fileRecyclerView.scrollIntoView(this) - val fileInfoMenu = this.getChild(UiSelector().resourceId(getViewIdentifier("menuButton"))) - fileInfoMenu.click() - val menuView = UiScrollable(UiSelector().resourceId(getViewIdentifier("scrollView"))) - menuView.scrollForward() - menuView.getChild(UiSelector().resourceId(getViewIdentifier("deleteFile"))).click() + getChild(UiSelector().resourceId(getViewIdentifier("menuButton"))).click() + UiScrollable(UiSelector().resourceId(getViewIdentifier("scrollView"))).apply { + scrollForward() + getChild(UiSelector().resourceId(getViewIdentifier("deleteFile"))).click() + } } device.findObject(UiSelector().text(context.getString(R.string.buttonMove))).clickAndWaitForNewWindow() } @@ -95,14 +95,12 @@ object UiTestUtils { fun openFileShareDetails(fileRecyclerView: UiScrollable, fileName: String) { (fileRecyclerView.getChildByText(UiSelector().resourceId(getViewIdentifier("fileCardView")), fileName)).apply { fileRecyclerView.scrollIntoView(this) - swipeLeft(3) - getChild((UiSelector().resourceId(getViewIdentifier("menuButton")))).clickAndWaitForNewWindow() + getChild((UiSelector().resourceId(getViewIdentifier("menuButton")))).click() } - - getDeviceViewById("fileRights")?.clickAndWaitForNewWindow() + getDeviceViewById("fileRights").clickAndWaitForNewWindow() } - fun getDeviceViewById(id: String): UiObject? = device.findObject(UiSelector().resourceId(getViewIdentifier(id))) + fun getDeviceViewById(id: String): UiObject = device.findObject(UiSelector().resourceId(getViewIdentifier(id))) fun findFileInList(fileRecyclerView: UiScrollable, fileName: String): UiObject? { return try { @@ -111,4 +109,15 @@ object UiTestUtils { null } } + + fun createPublicShareLink(recyclerView: UiScrollable) { + recyclerView.getChildByText( + UiSelector().resourceId(getViewIdentifier("permissionTitle")), + context.getString(R.string.shareLinkPublicRightTitle) + ).click() + device.apply { + findObject(UiSelector().resourceId(getViewIdentifier("saveButton"))).clickAndWaitForNewWindow() + findObject(UiSelector().resourceId(getViewIdentifier("shareLinkButton"))).clickAndWaitForNewWindow() + } + } } \ No newline at end of file From 5985c731906ca7170a18ce921e9df5ebf76b2d26 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 18 Jan 2022 15:56:05 +0100 Subject: [PATCH 078/102] Upgrade to JUnit 5 --- app/build.gradle | 12 +- .../com/infomaniak/drive/ApiRepositoryTest.kt | 181 +++++++++--------- .../infomaniak/drive/FileControllerTest.kt | 80 ++++---- .../java/com/infomaniak/drive/KDriveTest.kt | 11 +- .../com/infomaniak/drive/ui/FileItemUiTest.kt | 11 +- .../com/infomaniak/drive/ui/FileListUiTest.kt | 17 +- .../com/infomaniak/drive/ui/HomeUiTest.kt | 48 +++-- .../com/infomaniak/drive/ui/MenuUiTest.kt | 6 +- .../infomaniak/drive/utils/ApiTestUtils.kt | 13 +- .../com/infomaniak/drive/utils/UiTestUtils.kt | 8 +- build.gradle | 1 + 11 files changed, 195 insertions(+), 193 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c778f381e9..2eaa985165 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,7 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' apply plugin: 'androidx.navigation.safeargs.kotlin' apply plugin: 'realm-android' +apply plugin: 'de.mannodermaus.android-junit5' android { @@ -16,8 +17,8 @@ android { versionCode 4_01_000_06 versionName '4.1.0' - testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' - + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunnerArgument("runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder") buildConfigField 'String', 'CLIENT_ID', '"9473D73C-C20F-4971-9E10-D957C563FA68"' buildConfigField 'String', 'DRIVE_API', '"https://drive.infomaniak.com/drive/"' buildConfigField 'String', 'DRIVE_API_V2', '"https://drive.infomaniak.com/2/drive/"' @@ -93,6 +94,7 @@ sentry { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':Core') + implementation 'androidx.test:core-ktx:1.4.0' def work_version = '2.7.1' implementation "androidx.work:work-runtime-ktx:$work_version" @@ -136,9 +138,11 @@ dependencies { testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.3' testImplementation 'io.github.serpro69:kotlin-faker:1.9.0' - testImplementation 'junit:junit:4.13.2' androidTestImplementation "androidx.work:work-testing:$work_version" androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' + androidTestImplementation("androidx.test:runner:1.4.0") + androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") + androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.3.0") + androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:1.3.0") } diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index c1c737bc74..ade39ae887 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -18,7 +18,6 @@ package com.infomaniak.drive import androidx.collection.arrayMapOf -import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.gson.JsonObject import com.infomaniak.drive.data.api.ApiRepository.addCategory import com.infomaniak.drive.data.api.ApiRepository.createCategory @@ -69,23 +68,28 @@ import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.ApiTestUtils.getCategory import com.infomaniak.drive.utils.ApiTestUtils.getShareLink import com.infomaniak.drive.utils.Utils.ROOT_ID -import org.junit.* -import org.junit.runner.RunWith +import com.infomaniak.lib.core.networking.HttpClient.okHttpClient +import kotlinx.coroutines.runBlocking +import okhttp3.OkHttpClient +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test /** * Logging activity testing class */ -@RunWith(AndroidJUnit4::class) class ApiRepositoryTest : KDriveTest() { private lateinit var testFile: File - @Before + @BeforeEach @Throws(Exception::class) fun setUp() { testFile = createFileForTest() } - @After + @AfterEach @Throws(Exception::class) fun tearDown() { deleteTestFile(testFile) @@ -99,9 +103,9 @@ class ApiRepositoryTest : KDriveTest() { @Test fun getUserProfile() { with(getUserProfile(okHttpClient)) { - assertApiResponse(this) - Assert.assertEquals("User ids should be the same", userDrive.userId, data?.id) - } + assertApiResponse(this) + assertEquals(userDrive.userId, data?.id, "User ids should be the same") + } } @Test @@ -112,7 +116,7 @@ class ApiRepositoryTest : KDriveTest() { // File must be a favorite with(getFileDetails(testFile)) { assertApiResponse(this) - Assert.assertTrue(data!!.isFavorite) + assertTrue(data!!.isFavorite, "File must be a favorite") } // Delete created Favorite @@ -120,7 +124,7 @@ class ApiRepositoryTest : KDriveTest() { // File must not be a favorite with(getFileDetails(testFile)) { assertApiResponse(this) - Assert.assertFalse(data!!.isFavorite) + assertFalse(data!!.isFavorite, "File must not be a favorite") } } @@ -134,14 +138,14 @@ class ApiRepositoryTest : KDriveTest() { // Get comments with(getFileComments(testFile, 1)) { assertApiResponse(this) - Assert.assertTrue("Test file should not have comments", data.isNullOrEmpty()) + assertTrue(data.isNullOrEmpty(), "Test file should not have comments") } // Post 2 comments val commentBody = "Hello world" val commentID = postFileComment(testFile, commentBody).let { assertApiResponse(it) - Assert.assertEquals(commentBody, it.data?.body) + assertEquals(commentBody, it.data?.body) it.data!!.id } @@ -149,49 +153,49 @@ class ApiRepositoryTest : KDriveTest() { assertApiResponse(it) it.data!!.id } - Assert.assertNotEquals("Comments id should be different", commentID, commentID2) + assertNotEquals(commentID, commentID2, "Comments id should be different") // Likes the second comment with(postFileCommentLike(testFile, commentID2)) { assertApiResponse(this) - Assert.assertTrue(data ?: false) + assertTrue(data ?: false) } // Get new comments with(getFileComments(testFile, 1)) { assertApiResponse(this) - Assert.assertEquals("There should be 2 comments on the test file", 2, data?.size) + assertEquals(2, data?.size, "There should be 2 comments on the test file") val likedComment = data?.find { comment -> comment.id == commentID2 }?.liked - Assert.assertNotNull("Liked comment should not be null", likedComment) - Assert.assertTrue("Comment should be liked", likedComment!!) + assertNotNull(likedComment, "Liked comment should not be null") + assertTrue(likedComment!!, "Comment should be liked") } // Delete first comment deleteFileComment(testFile, commentID) - Assert.assertEquals("There should be 1 comment on the test file", 1, getFileComments(testFile, 1).data?.size) + assertEquals(1, getFileComments(testFile, 1).data?.size, "There should be 1 comment on the test file") // Put second comment with(putFileComment(testFile, commentID2, "42")) { assertApiResponse(this) - Assert.assertTrue(data ?: false) + assertTrue(data ?: false) } // Unlike the comment with(postFileCommentUnlike(testFile, commentID2)) { assertApiResponse(this) - Assert.assertTrue(data ?: false) + assertTrue(data ?: false) } // Make sure data has been updated with(getFileComments(testFile, 1)) { val comment = data?.find { commentRes -> commentRes.id == commentID2 } assertApiResponse(this) - Assert.assertEquals( - "Comment should be equal to 42", + assertEquals( "42", - comment?.body + comment?.body, + "Comment should be equal to 42", ) - Assert.assertNotNull(comment) - Assert.assertFalse(comment!!.liked) + assertNotNull(comment) + assertFalse(comment!!.liked) } } @@ -200,16 +204,16 @@ class ApiRepositoryTest : KDriveTest() { val copyName = "test copy" val copyFile = duplicateFile(testFile, copyName, ROOT_ID).let { assertApiResponse(it) - Assert.assertEquals("The copy name should be equal to $copyName", copyName, it.data?.name) - Assert.assertNotEquals("The id should be different from the original file", testFile.id, it.data?.id) - Assert.assertEquals(testFile.driveColor, it.data?.driveColor) + assertEquals(copyName, it.data?.name, "The copy name should be equal to $copyName") + assertNotEquals(testFile.id, it.data?.id, "The id should be different from the original file") + assertEquals(testFile.driveColor, it.data?.driveColor) it.data!! } // Duplicate one more time with same name and location with(duplicateFile(testFile, copyName, ROOT_ID)) { assertApiResponse(this) - Assert.assertEquals("The copy name should be equal to $copyName (1)", "$copyName (1)", data?.name) + assertEquals("$copyName (1)", data?.name, "The copy name should be equal to $copyName (1)") deleteTestFile(data!!) } @@ -222,16 +226,16 @@ class ApiRepositoryTest : KDriveTest() { // Create test folder val folderName = "folder" with(createFolder(okHttpClient, userDrive.driveId, ROOT_ID, folderName)) { - Assert.assertNotNull(data) + assertNotNull(data) // Move file in the test folder assertApiResponse(moveFile(file, data!!)) val folderFileCount = getFileCount(data!!) assertApiResponse(folderFileCount) - Assert.assertEquals("There should be 1 file in the folder", 1, folderFileCount.data?.count) + assertEquals(1, folderFileCount.data?.count, "There should be 1 file in the folder") val folderData = getFileDetails(data!!).data - Assert.assertNotNull(folderData) - Assert.assertTrue(folderData!!.children.contains(file)) + assertNotNull(folderData) + assertTrue(folderData!!.children.contains(file)) deleteTestFile(folderData) } } @@ -240,7 +244,7 @@ class ApiRepositoryTest : KDriveTest() { fun createTeamFolder() { with(createTeamFolder(okHttpClient, userDrive.driveId, "teamFolder", true)) { assertApiResponse(this) - Assert.assertTrue("visibility should be 'is_team_space_folder", data!!.visibility.contains("is_team_space_folder")) + assertTrue(data!!.visibility.contains("is_team_space_folder"), "visibility should be 'is_team_space_folder'") deleteTestFile(data!!) } } @@ -258,17 +262,17 @@ class ApiRepositoryTest : KDriveTest() { ) with(postFileShareLink(testFile, body)) { assertApiResponse(this) - Assert.assertEquals("Permission should be public", "public", data!!.permission.name.lowercase()) - Assert.assertFalse("Block downloads should be false", data!!.blockDownloads) - Assert.assertFalse("Can edit should be false", data!!.canEdit) - Assert.assertFalse("Show stats should be false", data!!.showStats) - Assert.assertFalse("Block comments should be false", data!!.blockDownloads) - Assert.assertFalse("Block information should be false", data!!.blockInformation) + assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") + assertFalse(data!!.blockDownloads, "Block downloads should be false") + assertFalse(data!!.canEdit, "Can edit should be false") + assertFalse(data!!.showStats, "Show stats should be false") + assertFalse(data!!.blockDownloads, "Block comments should be false") + assertFalse(data!!.blockInformation, "Block information should be false") } with(getFileShare(okHttpClient, testFile)) { assertApiResponse(this) - Assert.assertEquals("Path should be the name of the file", "/${testFile.name}", data!!.path) + assertEquals("/${testFile.name}", data!!.path, "Path should be the name of the file") } val response = putFileShareLink( @@ -285,27 +289,28 @@ class ApiRepositoryTest : KDriveTest() { with(getShareLink(testFile)) { assertApiResponse(this) - Assert.assertEquals("Permission should be public", "public", data!!.permission.name.lowercase()) - Assert.assertTrue("block downloads should be true", data!!.blockDownloads) - Assert.assertTrue("can edit should be true", data!!.canEdit) - Assert.assertTrue("show stats should be true", data!!.showStats) - Assert.assertTrue("block comments should be true", data!!.blockDownloads) - Assert.assertTrue("Block information should be true", data!!.blockInformation) + assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") + assertTrue(data!!.blockDownloads, "block downloads should be true") + assertTrue(data!!.canEdit, "can edit should be true") + assertTrue(data!!.showStats, "show stats should be true") + assertTrue(data!!.blockDownloads, "block comments should be true") + assertTrue(data!!.blockInformation, "Block information should be true") } with(deleteFileShareLink(testFile)) { assertApiResponse(this) - Assert.assertTrue(data!!) + assertTrue(data!!) } - Assert.assertFalse(postFileShareCheck(testFile, body).isSuccess()) + assertFalse(postFileShareCheck(testFile, body).isSuccess()) } @Test fun shareLink() { val fileShareLink = postFileShare(testFile) - Assert.assertTrue( + assertTrue( + + fileShareLink.contains("https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share".toRegex()), "Link should match regex 'https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share/'", - fileShareLink.contains("https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share".toRegex()) ) } @@ -315,33 +320,32 @@ class ApiRepositoryTest : KDriveTest() { var color = "#0000FF" val categoryId = createCategory(userDrive.driveId, name, color).let { assertApiResponse(it) - Assert.assertEquals("Name of the category should be equals to '$name'", name, it.data?.name) - Assert.assertEquals("Color of the category should be equals to blue", color, it.data?.color) - it.data!!.id + assertEquals("category tests", it.data?.name, "Name of the category should be equals to 'category tests'") + assertEquals("#0000FF", it.data?.color, "Color of the category should be equals to blue") + it.data!!.id } // Create again the same category should fail - with(createCategory(userDrive.driveId, name, color)) { - Assert.assertFalse(isSuccess()) - Assert.assertEquals( - "Error description should be 'category already exist error'", + with(createCategory(userDrive.driveId, "category tests", "#0000FF")) { + assertFalse(isSuccess()) + assertEquals( "Category already exist error", - error?.description - ) + error?.description, + "Error description should be 'category already exist error'") } name = "update cat" color = "#FF0000" with(editCategory(userDrive.driveId, categoryId, name, color)) { assertApiResponse(this) - Assert.assertEquals("Name of the category should be equals to '$name'", name, data?.name) - Assert.assertEquals("Color of the category should be equals to red", color, data?.color) + assertEquals("update cat", data?.name, "Name of the category should be equals to 'update cat'") + assertEquals("#FF0000", data?.color, "Color of the category should be equals to red") } assertApiResponse(deleteCategory(userDrive.driveId, categoryId)) - Assert.assertNull( - "The category shouldn't be found anymore", + assertNull( getCategory(userDrive.driveId).data?.find { cat -> cat.id == categoryId }, + "The category shouldn't be found anymore", ) } @@ -349,20 +353,19 @@ class ApiRepositoryTest : KDriveTest() { fun addCategoryToFile() { // Create a test category val category = createCategory(userDrive.driveId, "test cat", "#FFF").data - Assert.assertNotNull(category) + assertNotNull(category) // Add the category to the test file addCategory(testFile, category!!.id) with(getFileDetails(testFile)) { assertApiResponse(this) - Assert.assertNotNull( - "The test category should be found", - data!!.categories.find { cat -> cat.id == category.id }) + assertNotNull( + data!!.categories.find { cat -> cat.id == category.id }, "The test category should be found") } // Delete the category before removing it from the test file deleteCategory(userDrive.driveId, category.id) with(getFileDetails(testFile)) { assertApiResponse(this) - Assert.assertTrue("The test file should not have category", data!!.categories.isNullOrEmpty()) + assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have category") } } @@ -370,14 +373,14 @@ class ApiRepositoryTest : KDriveTest() { fun removeCategoryToFile() { // Create a test category val category = createCategory(userDrive.driveId, "test cat", "#000").data - Assert.assertNotNull(category) + assertNotNull(category) // Add the category to the test file addCategory(testFile, category!!.id) // Remove the category removeCategory(testFile, category.id) with(getFileDetails(testFile)) { assertApiResponse(this) - Assert.assertTrue("The test file should not have a category", data!!.categories.isNullOrEmpty()) + assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have a category") } // Delete the test category and file deleteCategory(userDrive.driveId, category.id) @@ -387,15 +390,15 @@ class ApiRepositoryTest : KDriveTest() { fun getLastActivityTest() { with(getLastActivities(userDrive.driveId, 1)) { assertApiResponse(this) - Assert.assertTrue("Last activities shouldn't be empty or null", data!!.isNotEmpty()) + assertTrue(data!!.isNotEmpty(), "Last activities shouldn't be empty or null") } } - @Ignore("Don't know the wanted api behaviour") + @Disabled("Don't know the wanted api behaviour") @Test fun postTestFolderAccess() { val folder = createFolder(okHttpClient, userDrive.driveId, ROOT_ID, "folder").data - Assert.assertNotNull("test folder must not be null", folder) + assertNotNull(folder, "test folder must not be null") val postResponse = postFolderAccess(folder!!) assertApiResponse(postResponse) deleteTestFile(folder) @@ -406,9 +409,9 @@ class ApiRepositoryTest : KDriveTest() { // Create a folder to convert it in dropbox val name = "testFolder" val folder = createFolder(okHttpClient, userDrive.driveId, ROOT_ID, name, false).data - Assert.assertNotNull(folder) + assertNotNull(folder) // No dropbox yet - Assert.assertNull("not dropbox should be returned, data should be null", getDropBox(folder!!).data) + assertNull(getDropBox(folder!!).data, "not dropbox should be returned, data should be null") val maxSize = 16384L val body = arrayMapOf( @@ -419,15 +422,15 @@ class ApiRepositoryTest : KDriveTest() { // Add a dropBox val dropboxId = postDropBox(folder, body).let { assertApiResponse(it) - Assert.assertTrue("Email when finished must be true", it.data!!.emailWhenFinished) - Assert.assertEquals("Limit file size should be $maxSize", maxSize, it.data!!.limitFileSize) + assertTrue(it.data!!.emailWhenFinished, "Email when finished must be true") + assertEquals(maxSize, it.data!!.limitFileSize, "Limit file size should be $maxSize") it.data!!.id } with(getDropBox(folder)) { assertApiResponse(this) - Assert.assertEquals("Dropbox name should be '$name'", name, data!!.alias) - Assert.assertEquals("Dropbox id should be $dropboxId", dropboxId, data!!.id) + assertEquals(name, data!!.alias, "Dropbox name should be '$name'") + assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") } val updateBody = JsonObject().apply { addProperty("email_when_finished", false) @@ -436,19 +439,19 @@ class ApiRepositoryTest : KDriveTest() { with(updateDropBox(folder, updateBody)) { assertApiResponse(this) - Assert.assertTrue(data ?: false) + assertTrue(data ?: false) } with(getDropBox(folder)) { assertApiResponse(this) - Assert.assertEquals("Dropbox id should be $dropboxId", dropboxId, data!!.id) - Assert.assertEquals("Email when finished should be false", false, data!!.emailWhenFinished) - Assert.assertEquals("Limit file size should be ${maxSize * 2}", maxSize * 2, data!!.limitFileSize) + assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") + assertEquals(false, data!!.emailWhenFinished, "Email when finished should be false") + assertEquals(maxSize * 2, data!!.limitFileSize, "Limit file size should be ${maxSize * 2}") } assertApiResponse(deleteDropBox(folder)) // No dropbox left - Assert.assertNull("not dropbox should be returned, data should be null", getDropBox(folder).data) + assertNull(getDropBox(folder).data, "not dropbox should be returned, data should be null") deleteTestFile(folder) } @@ -489,7 +492,7 @@ class ApiRepositoryTest : KDriveTest() { assertApiResponse(emptyTrash(userDrive.driveId)) with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { assertApiResponse(this) - Assert.assertTrue("Trash should be empty", data!!.isEmpty()) + assertTrue(data!!.isEmpty(), "Trash should be empty") } // Create a new file, put it in trash then permanently delete it @@ -501,7 +504,7 @@ class ApiRepositoryTest : KDriveTest() { // Trash should still be empty with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { assertApiResponse(this) - Assert.assertTrue("Trash should be empty", data!!.isEmpty()) + assertTrue(data!!.isEmpty(), "Trash should be empty") } } @@ -511,4 +514,4 @@ class ApiRepositoryTest : KDriveTest() { val order = File.SortType.BIGGER assertApiResponse(getMySharedFiles(okHttpClient, userDrive.driveId, order.order, order.orderBy, 1)) } -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index 357f4a252d..ae54889e71 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -1,6 +1,5 @@ package com.infomaniak.drive -import androidx.test.ext.junit.runners.AndroidJUnit4 import com.infomaniak.drive.data.api.ApiRepository import com.infomaniak.drive.data.api.ApiRepository.getFileListForFolder import com.infomaniak.drive.data.api.ApiRepository.getLastModifiedFiles @@ -21,27 +20,26 @@ import com.infomaniak.drive.utils.Utils import io.realm.Realm import kotlinx.android.parcel.RawValue import kotlinx.coroutines.runBlocking -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import java.util.* /** * File Controllers testing class */ -@RunWith(AndroidJUnit4::class) class FileControllerTest : KDriveTest() { private lateinit var realm: Realm - @Before + @BeforeEach @Throws(Exception::class) fun setUp() { realm = Realm.getInstance(getConfig()) } - @After + @AfterEach @Throws(Exception::class) fun tearDown() { if (!realm.isClosed) realm.close() @@ -54,7 +52,7 @@ class FileControllerTest : KDriveTest() { // Create a folder under root with(ApiRepository.createFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, folderName, true)) { assertApiResponse(this) - Assert.assertEquals("The name should correspond", folderName, data?.name) + assertEquals(folderName, data?.name, "The name should correspond") // Delete the test folder deleteTestFile(data!!) } @@ -66,11 +64,11 @@ class FileControllerTest : KDriveTest() { // We check that we get the data saved in realm val localResult = getLocalRootFiles() - Assert.assertNotNull("local root files cannot be null", localResult) - Assert.assertFalse("local root files cannot be empty", localResult?.second.isNullOrEmpty()) - Assert.assertTrue( + assertNotNull(localResult, "local root files cannot be null") + assertFalse(localResult?.second.isNullOrEmpty(), "local root files cannot be empty") + assertTrue( + remoteResult?.second?.size == localResult?.second?.size, "the size of the local and remote files must be identical", - remoteResult?.second?.size == localResult?.second?.size ) } @@ -85,8 +83,8 @@ class FileControllerTest : KDriveTest() { // Search the deleted file with(ApiRepository.searchFiles(userDrive.driveId, remoteFile.name, order.order, order.orderBy, 1)) { - Assert.assertTrue("Api response must be a success", isSuccess()) - Assert.assertTrue("Founded files should be empty", data.isNullOrEmpty()) + assertTrue(isSuccess(), "Api response must be a success") + assertTrue(data.isNullOrEmpty(), "Founded files should be empty") } } @@ -97,8 +95,8 @@ class FileControllerTest : KDriveTest() { ApiRepository.postFavoriteFile(remoteFile) // Get remote favorite files val remoteResult = ApiRepository.getFavoriteFiles(Env.DRIVE_ID, File.SortType.NAME_AZ, 1) - Assert.assertTrue("get favorite files request must pass successfully", remoteResult.isSuccess()) - Assert.assertFalse("remote favorite files cannot be empty ", remoteResult.data.isNullOrEmpty()) + assertTrue(remoteResult.isSuccess(), "get favorite files request must pass successfully") + assertFalse(remoteResult.data.isNullOrEmpty(), "remote favorite files cannot be empty ") // Save remote favorite files in realm db test val remoteFavoriteFiles = remoteResult.data!! @@ -116,12 +114,12 @@ class FileControllerTest : KDriveTest() { ) val parent = localFavoriteFiles?.first val files = localFavoriteFiles?.second - Assert.assertNotNull("local favorite files cannot be null", localFavoriteFiles) - Assert.assertFalse("local favorite files cannot be empty", files.isNullOrEmpty()) + assertNotNull(localFavoriteFiles, "local favorite files cannot be null") + assertFalse(files.isNullOrEmpty(), "local favorite files cannot be empty") // Compare remote files and local files - Assert.assertTrue(parent?.id == FAVORITES_FILE_ID) - Assert.assertTrue("local files and remote files cannot be different", files?.size == remoteFavoriteFiles.size) + assertTrue(parent?.id == FAVORITES_FILE_ID) + assertTrue(files?.size == remoteFavoriteFiles.size, "local files and remote files cannot be different") // Delete Test file deleteTestFile(remoteFile) } @@ -136,8 +134,8 @@ class FileControllerTest : KDriveTest() { isCompletedRemoteFiles = isComplete } - Assert.assertNotNull("remote my shares data cannot be null", remoteFiles) - Assert.assertTrue("remote my shares data must be complete", isCompletedRemoteFiles) + assertNotNull(remoteFiles, "remote my shares data cannot be null") + assertTrue(isCompletedRemoteFiles, "remote my shares data must be complete") // Get local files val localFiles = arrayListOf() @@ -147,19 +145,19 @@ class FileControllerTest : KDriveTest() { isCompletedLocaleFiles = isComplete } - Assert.assertNotNull("local my shares data cannot be null", localFiles) - Assert.assertTrue("local my shares data must be complete", isCompletedLocaleFiles) + assertNotNull(localFiles, "local my shares data cannot be null") + assertTrue(isCompletedLocaleFiles, "local my shares data must be complete") // Compare remote files and local files - Assert.assertTrue("local files and remote files cannot be different", remoteFiles.size == localFiles.size) + assertTrue(remoteFiles.size == localFiles.size, "local files and remote files cannot be different") } @Test fun getPictures_CanGetRemoteSavedFilesFromRealm() { // Get remote pictures val apiResponseData = ApiRepository.getLastPictures(Env.DRIVE_ID, 1).let { - Assert.assertTrue("get pictures request must pass", it.isSuccess()) - Assert.assertFalse("get pictures response data cannot be null or empty", it.data.isNullOrEmpty()) + assertTrue(it.isSuccess(), "get pictures request must pass") + assertFalse(it.data.isNullOrEmpty(), "get pictures response data cannot be null or empty") it.data!! } @@ -168,11 +166,11 @@ class FileControllerTest : KDriveTest() { // Get saved remote files from realm with(FileController.getPicturesDrive(realm)) { - Assert.assertTrue("local pictures cannot be empty ", isNotEmpty()) + assertTrue(isNotEmpty(), "local pictures cannot be empty ") // Compare remote pictures with local pictures - Assert.assertTrue("remote files and local files are different", size == apiResponseData.size) - } + assertTrue(size == apiResponseData.size, "remote files and local files are different") } + } @Test @@ -197,8 +195,8 @@ class FileControllerTest : KDriveTest() { fun searchFile_FromRealm_IsCorrect() { val file = createAndStoreOfficeFile() with(searchFiles(file.name, File.SortType.NAME_AZ, customRealm = realm)) { - Assert.assertTrue("the list of search results must contain results", isNotEmpty()) - Assert.assertTrue("the search result must match", first().name.contains(file.name)) + assertTrue(isNotEmpty(), "the list of search results must contain results") + assertTrue(first().name.contains(file.name), "the search result must match") } deleteTestFile(file) } @@ -208,15 +206,15 @@ class FileControllerTest : KDriveTest() { getAndSaveRemoteRootFiles() with(getLocalRootFiles()) { // Check if remote files are stored - Assert.assertNotNull("local root files cannot be null", this) - Assert.assertFalse("local root files cannot be empty", this?.second.isNullOrEmpty()) + assertNotNull(this, "local root files cannot be null") + assertFalse(this?.second.isNullOrEmpty(), "local root files cannot be empty") } // Delete root files removeFile(Utils.ROOT_ID, customRealm = realm) // Check that all root files are deleted with(realm.where(File::class.java).findAll()) { - Assert.assertTrue("Realm must not contain any files", isNullOrEmpty()) + assertTrue(isNullOrEmpty(), "Realm must not contain any files") } } @@ -226,7 +224,7 @@ class FileControllerTest : KDriveTest() { with(getFileListForFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, order = File.SortType.NAME_AZ)) { assertApiResponse(this) // Use non null assertion because data nullability has been checked in assertApiResponse() - Assert.assertTrue("Root folder should contains files", data!!.children.isNotEmpty()) + assertTrue(data!!.children.isNotEmpty(), "Root folder should contains files") } } @@ -237,8 +235,8 @@ class FileControllerTest : KDriveTest() { assertApiResponse(renameFile(file, newName)) with(getLastModifiedFiles(userDrive.driveId)) { assertApiResponse(this) - Assert.assertEquals("Last modified file should have id ${file.id}", file.id, data!!.first().id) - Assert.assertEquals("File should be named '$newName'", newName, data!!.first().name) + assertEquals(file.id, data!!.first().id, "Last modified file should have id ${file.id}") + assertEquals(newName, data!!.first().name, "File should be named '$newName'") } deleteTestFile(file) @@ -247,7 +245,7 @@ class FileControllerTest : KDriveTest() { private fun getAndSaveRemoteRootFiles(): Pair>? { // Get and save remote root files in realm db test return getFilesFromCacheOrDownload(Utils.ROOT_ID, 1, true, userDrive = userDrive, customRealm = realm).also { - Assert.assertNotNull("remote root files cannot be null", it) + assertNotNull(it, "remote root files cannot be null") } } diff --git a/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt b/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt index 4a25d7c02a..5f4c2fabf9 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt @@ -32,9 +32,8 @@ import com.infomaniak.lib.login.ApiToken import io.realm.RealmConfiguration import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking -import okhttp3.OkHttpClient -import org.junit.AfterClass -import org.junit.BeforeClass +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll open class KDriveTest { companion object { @@ -43,7 +42,7 @@ open class KDriveTest { internal lateinit var userDrive: UserDrive internal lateinit var okHttpClient: OkHttpClient - @BeforeClass + @BeforeAll @JvmStatic fun beforeAll() { if (Env.USE_CURRENT_USER) { @@ -65,7 +64,7 @@ open class KDriveTest { okHttpClient = runBlocking { KDriveHttpClient.getHttpClient(user.id) } } - @AfterClass + @AfterAll @JvmStatic fun afterAll() { if (!Env.USE_CURRENT_USER) { @@ -80,4 +79,4 @@ open class KDriveTest { .modules(RealmModules.LocalFilesModule()) .build() } -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt index 180a7f86ae..faecdf284c 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.drive.ui -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import com.infomaniak.drive.utils.UiTestUtils @@ -27,21 +26,19 @@ import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier import com.infomaniak.drive.utils.UiTestUtils.startApp -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test import java.util.* /** * UI Tests relative to a file item (sharing, comments, details, activities) */ -@RunWith(AndroidJUnit4::class) class FileItemUiTest { - @Before + @BeforeEach fun init() { startApp() - getDeviceViewById("fileListFragment")?.click() + getDeviceViewById("fileListFragment").click() } @Test diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt index de30bc4c30..1bc7a858c0 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.drive.ui -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import com.infomaniak.drive.utils.UiTestUtils @@ -26,20 +25,18 @@ import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.findFileInList import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier import com.infomaniak.drive.utils.UiTestUtils.startApp -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test import java.util.* /** * UI Tests relative to file list (quick operations, file creation, upload, import, ...) */ -@RunWith(AndroidJUnit4::class) class FileListUiTest { - @Before + @BeforeEach fun init() { startApp() UiTestUtils.getDeviceViewById("fileListFragment").click() @@ -52,9 +49,9 @@ class FileListUiTest { UiTestUtils.createPrivateFolder(randomFolderName) device.waitForWindowUpdate(null, 5000) - assertNotNull("File must be found", findFileInList(fileRecyclerView, randomFolderName)) + assertNotNull(findFileInList(fileRecyclerView, randomFolderName), "File must be found") deleteFile(fileRecyclerView, randomFolderName) - assertNull("File must not be found", findFileInList(fileRecyclerView, randomFolderName)) + assertNull(findFileInList(fileRecyclerView, randomFolderName), "File must not be found") } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt index e7b644f972..6c938145b1 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt @@ -21,31 +21,27 @@ import android.content.Context import android.content.Intent import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.matcher.ViewMatchers.assertThat -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.uiautomator.By -import androidx.test.uiautomator.UiCollection -import androidx.test.uiautomator.UiSelector +import androidx.test.uiautomator.UiObjectNotFoundException import androidx.test.uiautomator.Until +import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.utils.AccountUtils import com.infomaniak.drive.utils.UiTestUtils.APP_PACKAGE -import com.infomaniak.drive.utils.UiTestUtils.DEFAULT_DRIVE_ID -import com.infomaniak.drive.utils.UiTestUtils.DEFAULT_DRIVE_NAME import com.infomaniak.drive.utils.UiTestUtils.LAUNCH_TIMEOUT import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById -import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier +import com.infomaniak.drive.utils.UiTestUtils.selectDriveInList import org.hamcrest.CoreMatchers.notNullValue -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test /** * UI Tests relative to a home (drive switch, drive activities, file search) */ -@RunWith(AndroidJUnit4::class) class HomeUiTest { - @Before + @BeforeEach fun startApp() { device.pressHome() @@ -62,23 +58,25 @@ class HomeUiTest { @Test fun testSwitchDrive() { - val switchDrive = getDeviceViewById("driveInfos") - switchDrive?.clickAndWaitForNewWindow() + // Change drive from homeFragment + getDeviceViewById("homeFragment").clickAndWaitForNewWindow() + if (DriveInfosController.getDrivesCount(AccountUtils.currentUserId) < 2) { + // finding switchDriveButton should throw because it only appears if user has at least 2 drives + Assertions.assertThrows(UiObjectNotFoundException::class.java) { + getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() + } - val driveRecyclerView = UiCollection(UiSelector().resourceId(getViewIdentifier("selectionRecyclerView"))) - - driveRecyclerView.getChildByInstance( - UiSelector().resourceId(getViewIdentifier("driveCard")), - driveRecyclerView.childCount - 1 - ).clickAndWaitForNewWindow() + } - switchDrive?.clickAndWaitForNewWindow() + getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() + selectDriveInList(0) - driveRecyclerView.getChildByText( - UiSelector().resourceId(getViewIdentifier("driveCard")), - DEFAULT_DRIVE_NAME - ).clickAndWaitForNewWindow() + val driveId = AccountUtils.currentDriveId - assert(AccountUtils.currentDriveId == DEFAULT_DRIVE_ID) + // Change drive from menuFragment + getDeviceViewById("menuFragment").clickAndWaitForNewWindow() + getDeviceViewById("driveIcon").clickAndWaitForNewWindow() + selectDriveInList(1) + assert(AccountUtils.currentDriveId != driveId) { "Drive id should be different" } } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index a0dd469c00..ca9b02e8ee 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -33,11 +33,11 @@ import com.infomaniak.drive.utils.UiTestUtils import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import org.hamcrest.CoreMatchers -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class MenuUiTest { - @Before + @BeforeEach fun startApp() { device.pressHome() diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt index 12bd7c697f..ccb5c703d1 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt @@ -25,20 +25,21 @@ import com.infomaniak.drive.data.models.ShareLink import com.infomaniak.drive.data.models.drive.Category import com.infomaniak.lib.core.models.ApiResponse import com.infomaniak.lib.core.utils.ApiController -import org.junit.Assert +import kotlinx.android.parcel.RawValue +import org.junit.jupiter.api.Assertions import java.util.* object ApiTestUtils { fun assertApiResponse(response: ApiResponse<*>) { - Assert.assertTrue("This should succeed", response.isSuccess()) - Assert.assertNull("There should be no error", response.error) - Assert.assertNotNull("The data cannot be null", response.data) + Assertions.assertTrue(response.isSuccess(), "This should succeed") + Assertions.assertNull(response.error, "There should be no error") + Assertions.assertNotNull(response.data, "The data cannot be null") } fun deleteTestFile(remoteFile: File) { val deleteResponse = ApiRepository.deleteFile(remoteFile) - Assert.assertTrue("created file couldn't be deleted from the remote", deleteResponse.isSuccess()) + Assertions.assertTrue(deleteResponse.isSuccess(), "created file couldn't be deleted from the remote") } fun createFileForTest(): File { @@ -55,4 +56,4 @@ object ApiTestUtils { fun getCategory(driveId: Int): ApiResponse> { return ApiController.callApi(ApiRoutes.createCategory(driveId), ApiController.ApiMethod.GET) } -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index 98f7ac6f38..e4ae70f031 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -29,8 +29,6 @@ import org.hamcrest.CoreMatchers object UiTestUtils { const val APP_PACKAGE = "com.infomaniak.drive" const val LAUNCH_TIMEOUT = 5000L - const val DEFAULT_DRIVE_NAME = "infomaniak" - const val DEFAULT_DRIVE_ID = 100338 var context: Context = ApplicationProvider.getApplicationContext() var device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -120,4 +118,10 @@ object UiTestUtils { findObject(UiSelector().resourceId(getViewIdentifier("shareLinkButton"))).clickAndWaitForNewWindow() } } + + fun selectDriveInList(instance: Int) { + UiCollection(UiSelector().resourceId(getViewIdentifier("selectRecyclerView"))).getChildByInstance( + UiSelector().resourceId(getViewIdentifier("itemSelectText")), instance + ).clickAndWaitForNewWindow() + } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 62057be828..fb09ec05f2 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.android.tools.build:gradle:7.0.4' classpath 'com.google.gms:google-services:4.3.10' + classpath "de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1" } } From 2226cf071d85cacc557012964c59aab64da75377 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 19 Jan 2022 13:18:13 +0100 Subject: [PATCH 079/102] Uniformize build.gradle --- app/build.gradle | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2eaa985165..9b27d1b590 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ android { versionName '4.1.0' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - testInstrumentationRunnerArgument("runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder") + testInstrumentationRunnerArgument "runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder" buildConfigField 'String', 'CLIENT_ID', '"9473D73C-C20F-4971-9E10-D957C563FA68"' buildConfigField 'String', 'DRIVE_API', '"https://drive.infomaniak.com/drive/"' buildConfigField 'String', 'DRIVE_API_V2', '"https://drive.infomaniak.com/2/drive/"' @@ -94,7 +94,6 @@ sentry { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':Core') - implementation 'androidx.test:core-ktx:1.4.0' def work_version = '2.7.1' implementation "androidx.work:work-runtime-ktx:$work_version" @@ -136,13 +135,16 @@ dependencies { implementation 'io.sentry:sentry-android:5.6.1' + implementation 'androidx.test:core-ktx:1.4.0' testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.3' testImplementation 'io.github.serpro69:kotlin-faker:1.9.0' androidTestImplementation "androidx.work:work-testing:$work_version" androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' - androidTestImplementation("androidx.test:runner:1.4.0") - androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") - androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.3.0") - androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:1.3.0") + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + + def junit_version = '1.3.0' + androidTestImplementation "de.mannodermaus.junit5:android-test-core:$junit_version" + androidTestRuntimeOnly "de.mannodermaus.junit5:android-test-runner:$junit_version" } From 15465c9b5fbf8da77e0709f299dac01e415af892 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 19 Jan 2022 14:14:35 +0100 Subject: [PATCH 080/102] change apply to run --- .../java/com/infomaniak/drive/utils/UiTestUtils.kt | 4 ++-- build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index e4ae70f031..05e944eb98 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -67,9 +67,9 @@ object UiTestUtils { permissionsRecyclerView.getChildByText( UiSelector().resourceId(getViewIdentifier("permissionCard")), context.getString(R.string.createFolderMeOnly) - ).apply { + ).run { permissionsRecyclerView.scrollIntoView(this) - this.click() + click() } getChildByText( UiSelector().resourceId(getViewIdentifier("createFolderButton")), diff --git a/build.gradle b/build.gradle index fb09ec05f2..767e9607f7 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.android.tools.build:gradle:7.0.4' classpath 'com.google.gms:google-services:4.3.10' - classpath "de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1" + classpath 'de.mannodermaus.gradle.plugins:android-junit5:1.7.1.1' } } From a0d16e71237f0743c242e110eaceded8b345ead1 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 24 Jan 2022 11:33:01 +0100 Subject: [PATCH 081/102] refactor ui --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 22 ++++++++++--------- .../infomaniak/drive/FileControllerTest.kt | 14 +++++++----- .../infomaniak/drive/utils/ApiTestUtils.kt | 21 +++++++++++------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index ade39ae887..e7f3f0fd7e 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -103,9 +103,9 @@ class ApiRepositoryTest : KDriveTest() { @Test fun getUserProfile() { with(getUserProfile(okHttpClient)) { - assertApiResponse(this) - assertEquals(userDrive.userId, data?.id, "User ids should be the same") - } + assertApiResponse(this) + assertEquals(userDrive.userId, data?.id, "User ids should be the same") + } } @Test @@ -322,7 +322,7 @@ class ApiRepositoryTest : KDriveTest() { assertApiResponse(it) assertEquals("category tests", it.data?.name, "Name of the category should be equals to 'category tests'") assertEquals("#0000FF", it.data?.color, "Color of the category should be equals to blue") - it.data!!.id + it.data!!.id } // Create again the same category should fail @@ -330,8 +330,9 @@ class ApiRepositoryTest : KDriveTest() { assertFalse(isSuccess()) assertEquals( "Category already exist error", - error?.description, - "Error description should be 'category already exist error'") + error?.description, + "Error description should be 'category already exist error'" + ) } name = "update cat" @@ -359,7 +360,8 @@ class ApiRepositoryTest : KDriveTest() { with(getFileDetails(testFile)) { assertApiResponse(this) assertNotNull( - data!!.categories.find { cat -> cat.id == category.id }, "The test category should be found") + data!!.categories.find { cat -> cat.id == category.id }, "The test category should be found" + ) } // Delete the category before removing it from the test file deleteCategory(userDrive.driveId, category.id) @@ -461,12 +463,12 @@ class ApiRepositoryTest : KDriveTest() { val newName = "Trash test" renameFile(file, newName) val modifiedFile = getLastModifiedFiles(userDrive.driveId).data?.first() - Assert.assertNotNull("Modified file should not be null", modifiedFile) + assertNotNull(modifiedFile, "Modified file should not be null") deleteTestFile(modifiedFile!!) with(getTrashFile(modifiedFile, File.SortType.RECENT, 1)) { assertApiResponse(this) - Assert.assertEquals("file id should be the same", file.id, data?.id) - Assert.assertEquals("file name should be updated to '$newName'", newName, data?.name) + assertEquals(file.id, data?.id, "file id should be the same") + assertEquals(newName, data?.name, "file name should be updated to '$newName'") } with(getDriveTrash(userDrive.driveId, File.SortType.RECENT, 1)) { diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index ae54889e71..eef1fa85df 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -4,13 +4,15 @@ import com.infomaniak.drive.data.api.ApiRepository import com.infomaniak.drive.data.api.ApiRepository.getFileListForFolder import com.infomaniak.drive.data.api.ApiRepository.getLastModifiedFiles import com.infomaniak.drive.data.api.ApiRepository.renameFile -import com.infomaniak.drive.data.cache.FileController import com.infomaniak.drive.data.cache.FileController.FAVORITES_FILE_ID import com.infomaniak.drive.data.cache.FileController.getFilesFromCacheOrDownload import com.infomaniak.drive.data.cache.FileController.getMySharedFiles +import com.infomaniak.drive.data.cache.FileController.getOfflineFiles +import com.infomaniak.drive.data.cache.FileController.getPicturesDrive import com.infomaniak.drive.data.cache.FileController.removeFile import com.infomaniak.drive.data.cache.FileController.saveFavoritesFiles import com.infomaniak.drive.data.cache.FileController.searchFiles +import com.infomaniak.drive.data.cache.FileController.storePicturesDrive import com.infomaniak.drive.data.models.File import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponse import com.infomaniak.drive.utils.ApiTestUtils.createFileForTest @@ -84,7 +86,7 @@ class FileControllerTest : KDriveTest() { // Search the deleted file with(ApiRepository.searchFiles(userDrive.driveId, remoteFile.name, order.order, order.orderBy, 1)) { assertTrue(isSuccess(), "Api response must be a success") - assertTrue(data.isNullOrEmpty(), "Founded files should be empty") + assertTrue(data.isNullOrEmpty(), "Founded files should be empty") } } @@ -157,15 +159,15 @@ class FileControllerTest : KDriveTest() { // Get remote pictures val apiResponseData = ApiRepository.getLastPictures(Env.DRIVE_ID, 1).let { assertTrue(it.isSuccess(), "get pictures request must pass") - assertFalse(it.data.isNullOrEmpty(), "get pictures response data cannot be null or empty") + assertFalse(it.data.isNullOrEmpty(), "get pictures response data cannot be null or empty") it.data!! } // Store remote pictures - FileController.storePicturesDrive(apiResponseData, customRealm = realm) + storePicturesDrive(apiResponseData, customRealm = realm) // Get saved remote files from realm - with(FileController.getPicturesDrive(realm)) { + with(getPicturesDrive(realm)) { assertTrue(isNotEmpty(), "local pictures cannot be empty ") // Compare remote pictures with local pictures @@ -207,7 +209,7 @@ class FileControllerTest : KDriveTest() { with(getLocalRootFiles()) { // Check if remote files are stored assertNotNull(this, "local root files cannot be null") - assertFalse(this?.second.isNullOrEmpty(), "local root files cannot be empty") + assertFalse(this?.second.isNullOrEmpty(), "local root files cannot be empty") } // Delete root files diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt index ccb5c703d1..363c968430 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt @@ -32,21 +32,26 @@ import java.util.* object ApiTestUtils { fun assertApiResponse(response: ApiResponse<*>) { - Assertions.assertTrue(response.isSuccess(), "This should succeed") - Assertions.assertNull(response.error, "There should be no error") - Assertions.assertNotNull(response.data, "The data cannot be null") + with(response) { + Assertions.assertTrue(isSuccess(), "This should succeed") + Assertions.assertNull(error, "There should be no error") + Assertions.assertNotNull(data, "The data cannot be null") + } } fun deleteTestFile(remoteFile: File) { - val deleteResponse = ApiRepository.deleteFile(remoteFile) - Assertions.assertTrue(deleteResponse.isSuccess(), "created file couldn't be deleted from the remote") + Assertions.assertTrue( + ApiRepository.deleteFile(remoteFile).isSuccess(), + "created file couldn't be deleted from the remote" + ) } fun createFileForTest(): File { val createFile = CreateFile("offline doc ${UUID.randomUUID()}", File.Office.DOCS.extension) - val apiResponse = ApiRepository.createOfficeFile(Env.DRIVE_ID, Utils.ROOT_ID, createFile) - assertApiResponse(apiResponse) - return apiResponse.data!! + return ApiRepository.createOfficeFile(Env.DRIVE_ID, Utils.ROOT_ID, createFile).let { + assertApiResponse(it) + it.data!! + } } fun getShareLink(file: File): ApiResponse { From 2fa4e39accc88bff0c9ef0f6a07eb56f97d7f513 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 24 Jan 2022 11:58:48 +0100 Subject: [PATCH 082/102] Delete useless imports --- .../androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt | 2 -- .../java/com/infomaniak/drive/FileControllerTest.kt | 3 +-- app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt | 1 + 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index e7f3f0fd7e..b2bde4aba7 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -68,8 +68,6 @@ import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.ApiTestUtils.getCategory import com.infomaniak.drive.utils.ApiTestUtils.getShareLink import com.infomaniak.drive.utils.Utils.ROOT_ID -import com.infomaniak.lib.core.networking.HttpClient.okHttpClient -import kotlinx.coroutines.runBlocking import okhttp3.OkHttpClient import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.* diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index eef1fa85df..7d2edf52c6 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -20,7 +20,6 @@ import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.Env import com.infomaniak.drive.utils.Utils import io.realm.Realm -import kotlinx.android.parcel.RawValue import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.* @@ -254,7 +253,7 @@ class FileControllerTest : KDriveTest() { private fun getLocalRootFiles() = getFilesFromCacheOrDownload(Utils.ROOT_ID, 1, false, userDrive = userDrive, customRealm = realm) - private fun createAndStoreOfficeFile(transaction: ((remoteFile: File) -> Unit)? = null): @RawValue File { + private fun createAndStoreOfficeFile(transaction: ((remoteFile: File) -> Unit)? = null): File { val remoteFile = createFileForTest() // Save the file as offline file transaction?.invoke(remoteFile) diff --git a/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt b/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt index 5f4c2fabf9..77acb83638 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/KDriveTest.kt @@ -32,6 +32,7 @@ import com.infomaniak.lib.login.ApiToken import io.realm.RealmConfiguration import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking +import okhttp3.OkHttpClient import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll From fd7eeda66e57d4753a7b3179216ca3135e8608d2 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 24 Jan 2022 17:19:27 +0100 Subject: [PATCH 083/102] refactor ui tests --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 330 +++++++++++------- .../infomaniak/drive/FileControllerTest.kt | 9 +- .../infomaniak/drive/utils/ApiTestUtils.kt | 29 +- 3 files changed, 231 insertions(+), 137 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index b2bde4aba7..0e04facb60 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -17,11 +17,9 @@ */ package com.infomaniak.drive -import androidx.collection.arrayMapOf import com.google.gson.JsonObject import com.infomaniak.drive.data.api.ApiRepository.addCategory import com.infomaniak.drive.data.api.ApiRepository.createCategory -import com.infomaniak.drive.data.api.ApiRepository.createFolder import com.infomaniak.drive.data.api.ApiRepository.createTeamFolder import com.infomaniak.drive.data.api.ApiRepository.deleteCategory import com.infomaniak.drive.data.api.ApiRepository.deleteDropBox @@ -41,12 +39,10 @@ import com.infomaniak.drive.data.api.ApiRepository.getFileCount import com.infomaniak.drive.data.api.ApiRepository.getFileDetails import com.infomaniak.drive.data.api.ApiRepository.getFileShare import com.infomaniak.drive.data.api.ApiRepository.getLastActivities -import com.infomaniak.drive.data.api.ApiRepository.getLastModifiedFiles import com.infomaniak.drive.data.api.ApiRepository.getMySharedFiles import com.infomaniak.drive.data.api.ApiRepository.getTrashFile import com.infomaniak.drive.data.api.ApiRepository.getUserProfile import com.infomaniak.drive.data.api.ApiRepository.moveFile -import com.infomaniak.drive.data.api.ApiRepository.postDropBox import com.infomaniak.drive.data.api.ApiRepository.postFavoriteFile import com.infomaniak.drive.data.api.ApiRepository.postFileComment import com.infomaniak.drive.data.api.ApiRepository.postFileCommentLike @@ -63,12 +59,14 @@ import com.infomaniak.drive.data.api.ApiRepository.updateDropBox import com.infomaniak.drive.data.api.ApiRoutes.postFileShare import com.infomaniak.drive.data.models.File import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponse +import com.infomaniak.drive.utils.ApiTestUtils.createDropBoxForTest import com.infomaniak.drive.utils.ApiTestUtils.createFileForTest +import com.infomaniak.drive.utils.ApiTestUtils.createFolderWithName import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.ApiTestUtils.getCategory import com.infomaniak.drive.utils.ApiTestUtils.getShareLink +import com.infomaniak.drive.utils.ApiTestUtils.putNewFileInTrash import com.infomaniak.drive.utils.Utils.ROOT_ID -import okhttp3.OkHttpClient import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach @@ -108,7 +106,7 @@ class ApiRepositoryTest : KDriveTest() { @Test fun manageFavoriteFileLifecycle() { - // Create favorite + // Creates favorite assertApiResponse(postFavoriteFile(testFile)) // File must be a favorite @@ -117,7 +115,7 @@ class ApiRepositoryTest : KDriveTest() { assertTrue(data!!.isFavorite, "File must be a favorite") } - // Delete created Favorite + // Deletes created Favorite assertApiResponse(deleteFavoriteFile(testFile)) // File must not be a favorite with(getFileDetails(testFile)) { @@ -128,72 +126,90 @@ class ApiRepositoryTest : KDriveTest() { @Test fun getFileActivities() { + renameFile(testFile, "new name") assertApiResponse(getFileActivities(testFile, 1)) } @Test - fun manageFileCommentLifeCycle() { - // Get comments - with(getFileComments(testFile, 1)) { + fun createCommentOnFile() { + // Posts 2 comments + val commentBody = "Hello world" + with(postFileComment(testFile, commentBody)) { assertApiResponse(this) - assertTrue(data.isNullOrEmpty(), "Test file should not have comments") + assertEquals(commentBody, data!!.body) } - // Post 2 comments - val commentBody = "Hello world" - val commentID = postFileComment(testFile, commentBody).let { - assertApiResponse(it) - assertEquals(commentBody, it.data?.body) - it.data!!.id + // Gets comments + with(getFileComments(testFile, 1)) { + assertApiResponse(this) + assertTrue(data!!.isNotEmpty(), "Test file should have 1 comment") + assertEquals(commentBody, data!![0].body, "Comment body should be $commentBody") } + } - val commentID2 = postFileComment(testFile, commentBody).let { + @Test + fun updateCommentOnFile() { + val commentId = postFileComment(testFile, "Hello world").let { assertApiResponse(it) it.data!!.id } - assertNotEquals(commentID, commentID2, "Comments id should be different") - - // Likes the second comment - with(postFileCommentLike(testFile, commentID2)) { + // Updates the comment + with(putFileComment(testFile, commentId, "42")) { assertApiResponse(this) assertTrue(data ?: false) } - // Get new comments + // Makes sure comment has been updated with(getFileComments(testFile, 1)) { assertApiResponse(this) - assertEquals(2, data?.size, "There should be 2 comments on the test file") - val likedComment = data?.find { comment -> comment.id == commentID2 }?.liked - assertNotNull(likedComment, "Liked comment should not be null") - assertTrue(likedComment!!, "Comment should be liked") + assertEquals("42", data!![0].body, "Comment body should be 42") } - // Delete first comment - deleteFileComment(testFile, commentID) - assertEquals(1, getFileComments(testFile, 1).data?.size, "There should be 1 comment on the test file") + } - // Put second comment - with(putFileComment(testFile, commentID2, "42")) { + @Test + fun deleteCommentOnFile() { + // Adds a comment on file then deletes it + with(postFileComment(testFile, "Hello world")) { + assertApiResponse(this) + // Delete the comment + deleteFileComment(testFile, data!!.id) + assertTrue(getFileComments(testFile, 1).data.isNullOrEmpty(), "There should not be comment on the test file") + } + } + + @Test + fun likesCommentOnFile() { + val commentBody = "Hello world" + val commentID = postFileComment(testFile, commentBody).let { + assertApiResponse(it) + it.data!!.id + } + + // Likes the comment + with(postFileCommentLike(testFile, commentID)) { assertApiResponse(this) assertTrue(data ?: false) } + // Gets the comment + with(getFileComments(testFile, 1)) { + assertApiResponse(this) + val comment = data!!.find { comment -> comment.id == commentID } + assertNotNull(comment, "Comment should not be null") + assertTrue(comment?.liked ?: false, "Comment should be liked") + } + // Unlike the comment - with(postFileCommentUnlike(testFile, commentID2)) { + with(postFileCommentUnlike(testFile, commentID)) { assertApiResponse(this) assertTrue(data ?: false) } // Make sure data has been updated with(getFileComments(testFile, 1)) { - val comment = data?.find { commentRes -> commentRes.id == commentID2 } - assertApiResponse(this) - assertEquals( - "42", - comment?.body, - "Comment should be equal to 42", - ) - assertNotNull(comment) - assertFalse(comment!!.liked) + val comment = data?.find { commentRes -> commentRes.id == commentID } + assertNotNull(comment, "Comment should not be null") + assertFalse(comment?.liked ?: true, "Comment should not be liked anymore") } } @@ -215,26 +231,32 @@ class ApiRepositoryTest : KDriveTest() { deleteTestFile(data!!) } + // Delete the copy deleteTestFile(copyFile) } @Test fun moveFileToAnotherFolder() { val file = createFileForTest() - // Create test folder + // Creates test folder val folderName = "folder" - with(createFolder(okHttpClient, userDrive.driveId, ROOT_ID, folderName)) { - assertNotNull(data) - // Move file in the test folder - assertApiResponse(moveFile(file, data!!)) - val folderFileCount = getFileCount(data!!) - assertApiResponse(folderFileCount) - assertEquals(1, folderFileCount.data?.count, "There should be 1 file in the folder") - - val folderData = getFileDetails(data!!).data - assertNotNull(folderData) - assertTrue(folderData!!.children.contains(file)) - deleteTestFile(folderData) + with(createFolderWithName(folderName)) { + // Moves file in the test folder + assertApiResponse(moveFile(file, this)) + + // Gets the count of file in the folder + with(getFileCount(this)) { + assertApiResponse(this) + assertEquals(1, data!!.count, "There should be 1 file in the folder") + } + + // Makes sure the folder contains the file + with(getFileDetails(this)) { + assertNotNull(data) + assertTrue(data!!.children.contains(file), "The file should be contained in the test folder") + } + // Deletes the test folder + deleteTestFile(this) } } @@ -258,6 +280,8 @@ class ApiRepositoryTest : KDriveTest() { "block_comments" to "false", "block_information" to "false" ) + + // Creates the share link with(postFileShareLink(testFile, body)) { assertApiResponse(this) assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") @@ -268,23 +292,27 @@ class ApiRepositoryTest : KDriveTest() { assertFalse(data!!.blockInformation, "Block information should be false") } + // Get the share link with(getFileShare(okHttpClient, testFile)) { assertApiResponse(this) assertEquals("/${testFile.name}", data!!.path, "Path should be the name of the file") } - val response = putFileShareLink( - testFile, mapOf( - "permission" to "public", - "block_downloads" to true, - "can_edit" to true, - "show_stats" to true, - "block_comments" to true, - "block_information" to true + // Modifies the share link + with( + putFileShareLink( + testFile, mapOf( + "permission" to "public", + "block_downloads" to true, + "can_edit" to true, + "show_stats" to true, + "block_comments" to true, + "block_information" to true + ) ) - ) - assertApiResponse(response) + ) { assertApiResponse(this) } + // Makes sure modification has been made with(getShareLink(testFile)) { assertApiResponse(this) assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") @@ -295,36 +323,37 @@ class ApiRepositoryTest : KDriveTest() { assertTrue(data!!.blockInformation, "Block information should be true") } + // Delete the shareLink with(deleteFileShareLink(testFile)) { assertApiResponse(this) assertTrue(data!!) } - assertFalse(postFileShareCheck(testFile, body).isSuccess()) + + assertFalse(postFileShareCheck(testFile, body).isSuccess(), "Share link check should fail") } @Test fun shareLink() { val fileShareLink = postFileShare(testFile) assertTrue( - fileShareLink.contains("https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share".toRegex()), "Link should match regex 'https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share/'", ) } @Test - fun manageCategoryLifecycle() { - var name = "category tests" - var color = "#0000FF" + fun createCategory() { + val color = "#0000FF" + val name = "category tests" val categoryId = createCategory(userDrive.driveId, name, color).let { assertApiResponse(it) - assertEquals("category tests", it.data?.name, "Name of the category should be equals to 'category tests'") - assertEquals("#0000FF", it.data?.color, "Color of the category should be equals to blue") + assertEquals(name, it.data?.name, "Name of the category should be equals to $name") + assertEquals(color, it.data?.color, "Color of the category should be equals to $color") it.data!!.id } // Create again the same category should fail - with(createCategory(userDrive.driveId, "category tests", "#0000FF")) { + with(createCategory(userDrive.driveId, name, color)) { assertFalse(isSuccess()) assertEquals( "Category already exist error", @@ -333,14 +362,7 @@ class ApiRepositoryTest : KDriveTest() { ) } - name = "update cat" - color = "#FF0000" - with(editCategory(userDrive.driveId, categoryId, name, color)) { - assertApiResponse(this) - assertEquals("update cat", data?.name, "Name of the category should be equals to 'update cat'") - assertEquals("#FF0000", data?.color, "Color of the category should be equals to red") - } - + // Delete the category assertApiResponse(deleteCategory(userDrive.driveId, categoryId)) assertNull( getCategory(userDrive.driveId).data?.find { cat -> cat.id == categoryId }, @@ -348,19 +370,40 @@ class ApiRepositoryTest : KDriveTest() { ) } + @Test + fun updateCategory() { + var color = "#0000FF" + var name = "category tests" + val categoryId = createCategory(userDrive.driveId, name, color).let { + assertNotNull(it.data) + it.data!!.id + } + + name = "update category" + color = "#FF0000" + // Edit the category by changing its color and name + with(editCategory(userDrive.driveId, categoryId, name, color)) { + assertApiResponse(this) + assertEquals(name, data?.name, "Name of the category should be equals to $name") + assertEquals(color, data?.color, "Color of the category should be equals to $color") + } + // Delete test Category + deleteCategory(userDrive.driveId, categoryId) + } + @Test fun addCategoryToFile() { // Create a test category - val category = createCategory(userDrive.driveId, "test cat", "#FFF").data + val category = createCategory(userDrive.driveId, "test category", "#FFF").data assertNotNull(category) + // Add the category to the test file addCategory(testFile, category!!.id) with(getFileDetails(testFile)) { assertApiResponse(this) - assertNotNull( - data!!.categories.find { cat -> cat.id == category.id }, "The test category should be found" - ) + assertNotNull(data!!.categories.find { it.id == category.id }, "The test category should be found") } + // Delete the category before removing it from the test file deleteCategory(userDrive.driveId, category.id) with(getFileDetails(testFile)) { @@ -373,16 +416,17 @@ class ApiRepositoryTest : KDriveTest() { fun removeCategoryToFile() { // Create a test category val category = createCategory(userDrive.driveId, "test cat", "#000").data - assertNotNull(category) + assertNotNull(category, "Category should not be null") // Add the category to the test file addCategory(testFile, category!!.id) // Remove the category removeCategory(testFile, category.id) + // Make sure the category is removed with(getFileDetails(testFile)) { assertApiResponse(this) assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have a category") } - // Delete the test category and file + // Delete the test category deleteCategory(userDrive.driveId, category.id) } @@ -397,97 +441,122 @@ class ApiRepositoryTest : KDriveTest() { @Disabled("Don't know the wanted api behaviour") @Test fun postTestFolderAccess() { - val folder = createFolder(okHttpClient, userDrive.driveId, ROOT_ID, "folder").data + val folder = createFolderWithName("folder") assertNotNull(folder, "test folder must not be null") - val postResponse = postFolderAccess(folder!!) + val postResponse = postFolderAccess(folder) assertApiResponse(postResponse) deleteTestFile(folder) } @Test - fun manageDropboxLifecycle() { + fun createDropboxFromFolder() { // Create a folder to convert it in dropbox val name = "testFolder" - val folder = createFolder(okHttpClient, userDrive.driveId, ROOT_ID, name, false).data - assertNotNull(folder) + val folder = createFolderWithName(name) // No dropbox yet - assertNull(getDropBox(folder!!).data, "not dropbox should be returned, data should be null") + assertNull(getDropBox(folder).data, "not dropbox should be returned, data should be null") val maxSize = 16384L - val body = arrayMapOf( - "email_when_finished" to true, - "limit_file_size" to maxSize, - "password" to "password" - ) - // Add a dropBox - val dropboxId = postDropBox(folder, body).let { - assertApiResponse(it) - assertTrue(it.data!!.emailWhenFinished, "Email when finished must be true") - assertEquals(maxSize, it.data!!.limitFileSize, "Limit file size should be $maxSize") - it.data!!.id + + // Add a dropBox with default body and get its id + val dropboxId = createDropBoxForTest(folder, maxSize).let { + assertTrue(it.emailWhenFinished, "Email when finished must be true") + assertEquals(maxSize, it.limitFileSize, "Limit file size should be $maxSize") + it.id } + // Get the dropbox with(getDropBox(folder)) { assertApiResponse(this) assertEquals(name, data!!.alias, "Dropbox name should be '$name'") assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") } + // Delete the folder + deleteTestFile(folder) + } + + @Test + fun updateDropBox() { + val folder = createFolderWithName("testFolder") + + val maxSize = 16384L + createDropBoxForTest(folder, maxSize) + + // Update the dropbox info val updateBody = JsonObject().apply { addProperty("email_when_finished", false) addProperty("limit_file_size", maxSize * 2) } - with(updateDropBox(folder, updateBody)) { assertApiResponse(this) assertTrue(data ?: false) } + // Make sure the dropbox has been updated with(getDropBox(folder)) { - assertApiResponse(this) - assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") - assertEquals(false, data!!.emailWhenFinished, "Email when finished should be false") - assertEquals(maxSize * 2, data!!.limitFileSize, "Limit file size should be ${maxSize * 2}") + assertFalse(data?.emailWhenFinished ?: true, "Email when finished should be false") + assertEquals(maxSize * 2, data?.limitFileSize, "Limit file size should be ${maxSize * 2}") } + //Delete the folder + deleteTestFile(folder) + } + + @Test + fun deleteDropbox() { + val folder = createFolderWithName("folder") + // Convert the folder to dropbox + createDropBoxForTest(folder, 16384L) + // Delete the dropbox assertApiResponse(deleteDropBox(folder)) - // No dropbox left + // Assert no dropbox left assertNull(getDropBox(folder).data, "not dropbox should be returned, data should be null") deleteTestFile(folder) } @Test - fun manageTrashLifecycle() { - val file = createFileForTest() - val newName = "Trash test" - renameFile(file, newName) - val modifiedFile = getLastModifiedFiles(userDrive.driveId).data?.first() - assertNotNull(modifiedFile, "Modified file should not be null") - deleteTestFile(modifiedFile!!) - with(getTrashFile(modifiedFile, File.SortType.RECENT, 1)) { + fun getTrashFiles() { + // Create File to put it in trash + val fileToDelete = putNewFileInTrash() + // Get the deleted File from the trash, info should be the same + with(getTrashFile(fileToDelete, File.SortType.RECENT, 1)) { assertApiResponse(this) - assertEquals(file.id, data?.id, "file id should be the same") - assertEquals(newName, data?.name, "file name should be updated to '$newName'") + assertEquals(fileToDelete.id, data?.id, "file id should be the same") } + } + @Test + fun getAllDriveTrashFiles() { + // Create File to put it in trash + val fileToDelete = putNewFileInTrash() + // Get all trash Files with(getDriveTrash(userDrive.driveId, File.SortType.RECENT, 1)) { assertApiResponse(this) - Assert.assertTrue("Trash should not be empty", data!!.isNotEmpty()) - Assert.assertEquals("Last trash file's id should be ${file.id}", file.id, data?.first()?.id) + assertTrue(data!!.isNotEmpty(), "Trash should not be empty") + assertEquals(fileToDelete.id, data?.first()?.id, "First trash testFile's id should be ${fileToDelete.id}") } + } - // Restore the file from the trash - assertApiResponse(postRestoreTrashFile(modifiedFile, mapOf("destination_directory_id" to ROOT_ID))) + @Test + fun restoreFileFromTrash() { + // Create File and put it in trash + val file = putNewFileInTrash() + // Restore file from trash + assertApiResponse(postRestoreTrashFile(file, mapOf("destination_folder_id" to ROOT_ID))) + // Get the trash files, the file restored should not be here with(getDriveTrash(userDrive.driveId, File.SortType.RECENT, 1)) { assertApiResponse(this) if (data!!.isNotEmpty()) { - Assert.assertNotEquals("Last trash file's id should not be ${file.id}", file.id, data?.first()?.id) + assertNotEquals(file.id, data?.first()?.id, "Last trash file's id should not be ${file.id}") } } - deleteTestFile(modifiedFile) + // Put the file in trash again + deleteTestFile(file) } + @Test - fun permanentlyDeleteFile() { + fun permanentlyDeleteFiles() { // Clean the trash to make sure nothing is left in assertApiResponse(emptyTrash(userDrive.driveId)) with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { @@ -496,12 +565,9 @@ class ApiRepositoryTest : KDriveTest() { } // Create a new file, put it in trash then permanently delete it - with(createFileForTest()) { - deleteTestFile(this) - deleteTrashFile(this) - } + deleteTrashFile(putNewFileInTrash()) - // Trash should still be empty + // Trash should still be empty because new file has been deleted from trash with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { assertApiResponse(this) assertTrue(data!!.isEmpty(), "Trash should be empty") diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index 7d2edf52c6..70fc0c4e8d 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -170,7 +170,8 @@ class FileControllerTest : KDriveTest() { assertTrue(isNotEmpty(), "local pictures cannot be empty ") // Compare remote pictures with local pictures - assertTrue(size == apiResponseData.size, "remote files and local files are different") } + assertTrue(size == apiResponseData.size, "remote files and local files are different") + } } @@ -182,9 +183,9 @@ class FileControllerTest : KDriveTest() { } // Get offline files - with(FileController.getOfflineFiles(null, customRealm = realm)) { - Assert.assertTrue("local offline files cannot be null", isNotEmpty()) - Assert.assertNotNull("stored file was not found in realm db", firstOrNull { it.id == file.id }) + with(getOfflineFiles(null, customRealm = realm)) { + assertTrue(isNotEmpty(), "local offline files cannot be null") + assertNotNull(firstOrNull { it.id == file.id }, "stored file was not found in realm db") } // Delete remote offline test files diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt index 363c968430..2682963694 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt @@ -17,15 +17,20 @@ */ package com.infomaniak.drive.utils +import androidx.collection.arrayMapOf +import com.infomaniak.drive.KDriveTest.Companion.okHttpClient +import com.infomaniak.drive.KDriveTest.Companion.userDrive import com.infomaniak.drive.data.api.ApiRepository +import com.infomaniak.drive.data.api.ApiRepository.createFolder +import com.infomaniak.drive.data.api.ApiRepository.postDropBox import com.infomaniak.drive.data.api.ApiRoutes import com.infomaniak.drive.data.models.CreateFile +import com.infomaniak.drive.data.models.DropBox import com.infomaniak.drive.data.models.File import com.infomaniak.drive.data.models.ShareLink import com.infomaniak.drive.data.models.drive.Category import com.infomaniak.lib.core.models.ApiResponse import com.infomaniak.lib.core.utils.ApiController -import kotlinx.android.parcel.RawValue import org.junit.jupiter.api.Assertions import java.util.* @@ -61,4 +66,26 @@ object ApiTestUtils { fun getCategory(driveId: Int): ApiResponse> { return ApiController.callApi(ApiRoutes.createCategory(driveId), ApiController.ApiMethod.GET) } + + fun putNewFileInTrash() = + // Creates a file, puts it in trash and returns it + createFileForTest().also { deleteTestFile(it) } + + fun createFolderWithName(name: String) = + createFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, name).let { + assertApiResponse(it) + it.data!! + } + + fun createDropBoxForTest(folder: File, maxSize: Long): DropBox { + val body = arrayMapOf( + "email_when_finished" to true, + "limit_file_size" to maxSize, + "password" to "password" + ) + return postDropBox(folder, body).let { + assertApiResponse(it) + it.data!! + } + } } From cf16a79c206d74beac7d288cb50e8b351e8b0c90 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 25 Jan 2022 11:29:59 +0100 Subject: [PATCH 084/102] add description and nested class in tests --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 529 +++++++++--------- 1 file changed, 268 insertions(+), 261 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 0e04facb60..ee9b68055a 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -67,36 +67,22 @@ import com.infomaniak.drive.utils.ApiTestUtils.getCategory import com.infomaniak.drive.utils.ApiTestUtils.getShareLink import com.infomaniak.drive.utils.ApiTestUtils.putNewFileInTrash import com.infomaniak.drive.utils.Utils.ROOT_ID -import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test /** * Logging activity testing class */ class ApiRepositoryTest : KDriveTest() { - private lateinit var testFile: File - - @BeforeEach - @Throws(Exception::class) - fun setUp() { - testFile = createFileForTest() - } - - @AfterEach - @Throws(Exception::class) - fun tearDown() { - deleteTestFile(testFile) - } @Test + @DisplayName("Check if remote drive data are correctly retrieved") fun getDriveData() { assertApiResponse(getAllDrivesData(okHttpClient)) } @Test + @DisplayName("Check if remote user profile is correctly retrieved") fun getUserProfile() { with(getUserProfile(okHttpClient)) { assertApiResponse(this) @@ -104,137 +90,6 @@ class ApiRepositoryTest : KDriveTest() { } } - @Test - fun manageFavoriteFileLifecycle() { - // Creates favorite - assertApiResponse(postFavoriteFile(testFile)) - - // File must be a favorite - with(getFileDetails(testFile)) { - assertApiResponse(this) - assertTrue(data!!.isFavorite, "File must be a favorite") - } - - // Deletes created Favorite - assertApiResponse(deleteFavoriteFile(testFile)) - // File must not be a favorite - with(getFileDetails(testFile)) { - assertApiResponse(this) - assertFalse(data!!.isFavorite, "File must not be a favorite") - } - } - - @Test - fun getFileActivities() { - renameFile(testFile, "new name") - assertApiResponse(getFileActivities(testFile, 1)) - } - - @Test - fun createCommentOnFile() { - // Posts 2 comments - val commentBody = "Hello world" - with(postFileComment(testFile, commentBody)) { - assertApiResponse(this) - assertEquals(commentBody, data!!.body) - } - - // Gets comments - with(getFileComments(testFile, 1)) { - assertApiResponse(this) - assertTrue(data!!.isNotEmpty(), "Test file should have 1 comment") - assertEquals(commentBody, data!![0].body, "Comment body should be $commentBody") - } - } - - @Test - fun updateCommentOnFile() { - val commentId = postFileComment(testFile, "Hello world").let { - assertApiResponse(it) - it.data!!.id - } - // Updates the comment - with(putFileComment(testFile, commentId, "42")) { - assertApiResponse(this) - assertTrue(data ?: false) - } - - // Makes sure comment has been updated - with(getFileComments(testFile, 1)) { - assertApiResponse(this) - assertEquals("42", data!![0].body, "Comment body should be 42") - } - } - - @Test - fun deleteCommentOnFile() { - // Adds a comment on file then deletes it - with(postFileComment(testFile, "Hello world")) { - assertApiResponse(this) - // Delete the comment - deleteFileComment(testFile, data!!.id) - assertTrue(getFileComments(testFile, 1).data.isNullOrEmpty(), "There should not be comment on the test file") - } - } - - @Test - fun likesCommentOnFile() { - val commentBody = "Hello world" - val commentID = postFileComment(testFile, commentBody).let { - assertApiResponse(it) - it.data!!.id - } - - // Likes the comment - with(postFileCommentLike(testFile, commentID)) { - assertApiResponse(this) - assertTrue(data ?: false) - } - - // Gets the comment - with(getFileComments(testFile, 1)) { - assertApiResponse(this) - val comment = data!!.find { comment -> comment.id == commentID } - assertNotNull(comment, "Comment should not be null") - assertTrue(comment?.liked ?: false, "Comment should be liked") - } - - // Unlike the comment - with(postFileCommentUnlike(testFile, commentID)) { - assertApiResponse(this) - assertTrue(data ?: false) - } - - // Make sure data has been updated - with(getFileComments(testFile, 1)) { - val comment = data?.find { commentRes -> commentRes.id == commentID } - assertNotNull(comment, "Comment should not be null") - assertFalse(comment?.liked ?: true, "Comment should not be liked anymore") - } - } - - @Test - fun duplicateFile() { - val copyName = "test copy" - val copyFile = duplicateFile(testFile, copyName, ROOT_ID).let { - assertApiResponse(it) - assertEquals(copyName, it.data?.name, "The copy name should be equal to $copyName") - assertNotEquals(testFile.id, it.data?.id, "The id should be different from the original file") - assertEquals(testFile.driveColor, it.data?.driveColor) - it.data!! - } - - // Duplicate one more time with same name and location - with(duplicateFile(testFile, copyName, ROOT_ID)) { - assertApiResponse(this) - assertEquals("$copyName (1)", data?.name, "The copy name should be equal to $copyName (1)") - deleteTestFile(data!!) - } - - // Delete the copy - deleteTestFile(copyFile) - } - @Test fun moveFileToAnotherFolder() { val file = createFileForTest() @@ -269,78 +124,6 @@ class ApiRepositoryTest : KDriveTest() { } } - @Test - fun shareLinkTest() { - // TODO Changes for api-v2 : boolean instead of "true", "false", and can_edit instead of canEdit - val body = mapOf( - "permission" to "public", - "block_downloads" to "false", - "canEdit" to "false", - "show_stats" to "false", - "block_comments" to "false", - "block_information" to "false" - ) - - // Creates the share link - with(postFileShareLink(testFile, body)) { - assertApiResponse(this) - assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") - assertFalse(data!!.blockDownloads, "Block downloads should be false") - assertFalse(data!!.canEdit, "Can edit should be false") - assertFalse(data!!.showStats, "Show stats should be false") - assertFalse(data!!.blockDownloads, "Block comments should be false") - assertFalse(data!!.blockInformation, "Block information should be false") - } - - // Get the share link - with(getFileShare(okHttpClient, testFile)) { - assertApiResponse(this) - assertEquals("/${testFile.name}", data!!.path, "Path should be the name of the file") - } - - // Modifies the share link - with( - putFileShareLink( - testFile, mapOf( - "permission" to "public", - "block_downloads" to true, - "can_edit" to true, - "show_stats" to true, - "block_comments" to true, - "block_information" to true - ) - ) - ) { assertApiResponse(this) } - - // Makes sure modification has been made - with(getShareLink(testFile)) { - assertApiResponse(this) - assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") - assertTrue(data!!.blockDownloads, "block downloads should be true") - assertTrue(data!!.canEdit, "can edit should be true") - assertTrue(data!!.showStats, "show stats should be true") - assertTrue(data!!.blockDownloads, "block comments should be true") - assertTrue(data!!.blockInformation, "Block information should be true") - } - - // Delete the shareLink - with(deleteFileShareLink(testFile)) { - assertApiResponse(this) - assertTrue(data!!) - } - - assertFalse(postFileShareCheck(testFile, body).isSuccess(), "Share link check should fail") - } - - @Test - fun shareLink() { - val fileShareLink = postFileShare(testFile) - assertTrue( - fileShareLink.contains("https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share".toRegex()), - "Link should match regex 'https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share/'", - ) - } - @Test fun createCategory() { val color = "#0000FF" @@ -391,47 +174,9 @@ class ApiRepositoryTest : KDriveTest() { deleteCategory(userDrive.driveId, categoryId) } - @Test - fun addCategoryToFile() { - // Create a test category - val category = createCategory(userDrive.driveId, "test category", "#FFF").data - assertNotNull(category) - - // Add the category to the test file - addCategory(testFile, category!!.id) - with(getFileDetails(testFile)) { - assertApiResponse(this) - assertNotNull(data!!.categories.find { it.id == category.id }, "The test category should be found") - } - - // Delete the category before removing it from the test file - deleteCategory(userDrive.driveId, category.id) - with(getFileDetails(testFile)) { - assertApiResponse(this) - assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have category") - } - } - - @Test - fun removeCategoryToFile() { - // Create a test category - val category = createCategory(userDrive.driveId, "test cat", "#000").data - assertNotNull(category, "Category should not be null") - // Add the category to the test file - addCategory(testFile, category!!.id) - // Remove the category - removeCategory(testFile, category.id) - // Make sure the category is removed - with(getFileDetails(testFile)) { - assertApiResponse(this) - assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have a category") - } - // Delete the test category - deleteCategory(userDrive.driveId, category.id) - } @Test - fun getLastActivityTest() { + fun getLastActivity() { with(getLastActivities(userDrive.driveId, 1)) { assertApiResponse(this) assertTrue(data!!.isNotEmpty(), "Last activities shouldn't be empty or null") @@ -554,7 +299,6 @@ class ApiRepositoryTest : KDriveTest() { deleteTestFile(file) } - @Test fun permanentlyDeleteFiles() { // Clean the trash to make sure nothing is left in @@ -574,10 +318,273 @@ class ApiRepositoryTest : KDriveTest() { } } - @Test fun mySharedFileTest() { val order = File.SortType.BIGGER assertApiResponse(getMySharedFiles(okHttpClient, userDrive.driveId, order.order, order.orderBy, 1)) } + + @Nested + @DisplayName("Class for tests needing testFile") + private inner class ShareTestFile { + + private lateinit var testFile: File + + @BeforeEach + @Throws(Exception::class) + fun setUp() { + testFile = createFileForTest() + } + + @AfterEach + @Throws(Exception::class) + fun tearDown() { + deleteTestFile(testFile) + } + + @Test + @DisplayName("Check if a file can be added the deleted from favorite") + fun manageFavoriteFileLifecycle() { + // Creates favorite + assertApiResponse(postFavoriteFile(testFile)) + + // File must be a favorite + with(getFileDetails(testFile)) { + assertApiResponse(this) + assertTrue(data!!.isFavorite, "File must be a favorite") + } + + // Deletes created Favorite + assertApiResponse(deleteFavoriteFile(testFile)) + // File must not be a favorite + with(getFileDetails(testFile)) { + assertApiResponse(this) + assertFalse(data!!.isFavorite, "File must not be a favorite") + } + } + + @Test + @DisplayName("Check if the file activities are correctly retrieved") + fun getFileActivities() { + renameFile(testFile, "new name") + assertApiResponse(getFileActivities(testFile, 1)) + } + + @Test + @DisplayName("Check the creation of comment on a file") + fun createCommentOnFile() { + // Posts 2 comments + val commentBody = "Hello world" + with(postFileComment(testFile, commentBody)) { + assertApiResponse(this) + assertEquals(commentBody, data!!.body) + } + + // Gets comments + with(getFileComments(testFile, 1)) { + assertApiResponse(this) + assertTrue(data!!.isNotEmpty(), "Test file should have 1 comment") + assertEquals(commentBody, data!![0].body, "Comment body should be $commentBody") + } + } + + @Test + fun updateCommentOnFile() { + val commentId = postFileComment(testFile, "Hello world").let { + assertApiResponse(it) + it.data!!.id + } + // Updates the comment + with(putFileComment(testFile, commentId, "42")) { + assertApiResponse(this) + assertTrue(data ?: false) + } + + // Makes sure comment has been updated + with(getFileComments(testFile, 1)) { + assertApiResponse(this) + assertEquals("42", data!![0].body, "Comment body should be 42") + } + } + + @Test + fun deleteCommentOnFile() { + // Adds a comment on file then deletes it + with(postFileComment(testFile, "Hello world")) { + assertApiResponse(this) + // Delete the comment + deleteFileComment(testFile, data!!.id) + assertTrue(getFileComments(testFile, 1).data.isNullOrEmpty(), "There should not be comment on the test file") + } + } + + @Test + fun likesCommentOnFile() { + val commentBody = "Hello world" + val commentID = postFileComment(testFile, commentBody).let { + assertApiResponse(it) + it.data!!.id + } + + // Likes the comment + with(postFileCommentLike(testFile, commentID)) { + assertApiResponse(this) + assertTrue(data ?: false) + } + + // Gets the comment + with(getFileComments(testFile, 1)) { + assertApiResponse(this) + val comment = data!!.find { comment -> comment.id == commentID } + assertNotNull(comment, "Comment should not be null") + assertTrue(comment?.liked ?: false, "Comment should be liked") + } + + // Unlike the comment + with(postFileCommentUnlike(testFile, commentID)) { + assertApiResponse(this) + assertTrue(data ?: false) + } + + // Make sure data has been updated + with(getFileComments(testFile, 1)) { + val comment = data?.find { commentRes -> commentRes.id == commentID } + assertNotNull(comment, "Comment should not be null") + assertFalse(comment?.liked ?: true, "Comment should not be liked anymore") + } + } + + @Test + fun duplicateFile() { + val copyName = "test copy" + val copyFile = duplicateFile(testFile, copyName, ROOT_ID).let { + assertApiResponse(it) + assertEquals(copyName, it.data?.name, "The copy name should be equal to $copyName") + assertNotEquals(testFile.id, it.data?.id, "The id should be different from the original file") + assertEquals(testFile.driveColor, it.data?.driveColor) + it.data!! + } + + // Duplicate one more time with same name and location + with(duplicateFile(testFile, copyName, ROOT_ID)) { + assertApiResponse(this) + assertEquals("$copyName (1)", data?.name, "The copy name should be equal to $copyName (1)") + deleteTestFile(data!!) + } + + // Delete the copy + deleteTestFile(copyFile) + } + + @Test + fun shareLinkTest() { + // TODO Changes for api-v2 : boolean instead of "true", "false", and can_edit instead of canEdit + val body = mapOf( + "permission" to "public", + "block_downloads" to "false", + "canEdit" to "false", + "show_stats" to "false", + "block_comments" to "false", + "block_information" to "false" + ) + + // Creates the share link + with(postFileShareLink(testFile, body)) { + assertApiResponse(this) + assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") + assertFalse(data!!.blockDownloads, "Block downloads should be false") + assertFalse(data!!.canEdit, "Can edit should be false") + assertFalse(data!!.showStats, "Show stats should be false") + assertFalse(data!!.blockDownloads, "Block comments should be false") + assertFalse(data!!.blockInformation, "Block information should be false") + } + + // Get the share link + with(getFileShare(okHttpClient, testFile)) { + assertApiResponse(this) + assertEquals("/${testFile.name}", data!!.path, "Path should be the name of the file") + } + + // Modifies the share link + with( + putFileShareLink( + testFile, mapOf( + "permission" to "public", + "block_downloads" to true, + "can_edit" to true, + "show_stats" to true, + "block_comments" to true, + "block_information" to true + ) + ) + ) { assertApiResponse(this) } + + // Makes sure modification has been made + with(getShareLink(testFile)) { + assertApiResponse(this) + assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") + assertTrue(data!!.blockDownloads, "block downloads should be true") + assertTrue(data!!.canEdit, "can edit should be true") + assertTrue(data!!.showStats, "show stats should be true") + assertTrue(data!!.blockDownloads, "block comments should be true") + assertTrue(data!!.blockInformation, "Block information should be true") + } + + // Delete the shareLink + with(deleteFileShareLink(testFile)) { + assertApiResponse(this) + assertTrue(data!!) + } + + assertFalse(postFileShareCheck(testFile, body).isSuccess(), "Share link check should fail") + } + + @Test + fun shareLink() { + val fileShareLink = postFileShare(testFile) + assertTrue( + fileShareLink.contains("https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share".toRegex()), + "Link should match regex 'https://drive.infomaniak.com/drive/[0-9]+/file/[0-9]+/share/'", + ) + } + + @Test + fun addCategoryToFile() { + // Create a test category + val category = createCategory(userDrive.driveId, "test category", "#FFF").data + assertNotNull(category) + + // Add the category to the test file + addCategory(testFile, category!!.id) + with(getFileDetails(testFile)) { + assertApiResponse(this) + assertNotNull(data!!.categories.find { it.id == category.id }, "The test category should be found") + } + + // Delete the category before removing it from the test file + deleteCategory(userDrive.driveId, category.id) + with(getFileDetails(testFile)) { + assertApiResponse(this) + assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have category") + } + } + + @Test + fun removeCategoryToFile() { + // Create a test category + val category = createCategory(userDrive.driveId, "test cat", "#000").data + assertNotNull(category, "Category should not be null") + // Add the category to the test file + addCategory(testFile, category!!.id) + // Remove the category + removeCategory(testFile, category.id) + // Make sure the category is removed + with(getFileDetails(testFile)) { + assertApiResponse(this) + assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have a category") + } + // Delete the test category + deleteCategory(userDrive.driveId, category.id) + } + } } From fe539e144338c5f7268784e5a4eefb26e93b4cc6 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 25 Jan 2022 11:48:06 +0100 Subject: [PATCH 085/102] add display name to tests --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index ee9b68055a..7858ecf5c7 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -83,7 +83,7 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Check if remote user profile is correctly retrieved") - fun getUserProfile() { + fun getUserProfileFromRemote() { with(getUserProfile(okHttpClient)) { assertApiResponse(this) assertEquals(userDrive.userId, data?.id, "User ids should be the same") @@ -91,6 +91,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a file under root then move it to a created folder") fun moveFileToAnotherFolder() { val file = createFileForTest() // Creates test folder @@ -116,6 +117,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a folder with team space visibility") fun createTeamFolder() { with(createTeamFolder(okHttpClient, userDrive.driveId, "teamFolder", true)) { assertApiResponse(this) @@ -125,6 +127,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a category then delete it") fun createCategory() { val color = "#0000FF" val name = "category tests" @@ -154,6 +157,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Update a created category then delete it") fun updateCategory() { var color = "#0000FF" var name = "category tests" @@ -176,6 +180,7 @@ class ApiRepositoryTest : KDriveTest() { @Test + @DisplayName("Retrieve recent activities from remote") fun getLastActivity() { with(getLastActivities(userDrive.driveId, 1)) { assertApiResponse(this) @@ -194,8 +199,9 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a folder then convert it to dropbox") fun createDropboxFromFolder() { - // Create a folder to convert it in dropbox + // Create a folder to convert it to dropbox val name = "testFolder" val folder = createFolderWithName(name) // No dropbox yet @@ -221,6 +227,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Update the properties of a dropbox") fun updateDropBox() { val folder = createFolderWithName("testFolder") @@ -248,6 +255,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Convert a dropbox back to a normal folder") fun deleteDropbox() { val folder = createFolderWithName("folder") // Convert the folder to dropbox @@ -260,6 +268,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Put a file in trash then find it trash files") fun getTrashFiles() { // Create File to put it in trash val fileToDelete = putNewFileInTrash() @@ -271,6 +280,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("") fun getAllDriveTrashFiles() { // Create File to put it in trash val fileToDelete = putNewFileInTrash() From 812fe8c42ae2ee6afcf3b88792420a27331b6b7d Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 25 Jan 2022 16:58:36 +0100 Subject: [PATCH 086/102] Add name to tests --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 24 ++++++++++++++----- .../infomaniak/drive/FileControllerTest.kt | 15 ++++++++++-- .../com/infomaniak/drive/ui/FileItemUiTest.kt | 2 ++ .../com/infomaniak/drive/ui/FileListUiTest.kt | 2 ++ .../com/infomaniak/drive/ui/HomeUiTest.kt | 2 ++ .../com/infomaniak/drive/ui/MenuUiTest.kt | 2 ++ 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 7858ecf5c7..30413e7e49 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -190,6 +190,7 @@ class ApiRepositoryTest : KDriveTest() { @Disabled("Don't know the wanted api behaviour") @Test + @DisplayName("Create a folder and post its access permissions") fun postTestFolderAccess() { val folder = createFolderWithName("folder") assertNotNull(folder, "test folder must not be null") @@ -268,8 +269,8 @@ class ApiRepositoryTest : KDriveTest() { } @Test - @DisplayName("Put a file in trash then find it trash files") - fun getTrashFiles() { + @DisplayName("Put a file in trash then get it from here") + fun getGivenTrashFile() { // Create File to put it in trash val fileToDelete = putNewFileInTrash() // Get the deleted File from the trash, info should be the same @@ -280,7 +281,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test - @DisplayName("") + @DisplayName("Put a file in trash then get all files in trash") fun getAllDriveTrashFiles() { // Create File to put it in trash val fileToDelete = putNewFileInTrash() @@ -293,6 +294,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Put a file in trash then restore it to root folder") fun restoreFileFromTrash() { // Create File and put it in trash val file = putNewFileInTrash() @@ -310,6 +312,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Delete all trashed files, then delete one created file specifically") fun permanentlyDeleteFiles() { // Clean the trash to make sure nothing is left in assertApiResponse(emptyTrash(userDrive.driveId)) @@ -329,14 +332,15 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Retrieve shared remote file") fun mySharedFileTest() { val order = File.SortType.BIGGER assertApiResponse(getMySharedFiles(okHttpClient, userDrive.driveId, order.order, order.orderBy, 1)) } @Nested - @DisplayName("Class for tests needing testFile") - private inner class ShareTestFile { + @DisplayName("Given test file") + inner class ShareTestFile { private lateinit var testFile: File @@ -353,7 +357,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test - @DisplayName("Check if a file can be added the deleted from favorite") + @DisplayName("Add a file to favorite, then remove it") fun manageFavoriteFileLifecycle() { // Creates favorite assertApiResponse(postFavoriteFile(testFile)) @@ -399,6 +403,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a comment on a file then update it") fun updateCommentOnFile() { val commentId = postFileComment(testFile, "Hello world").let { assertApiResponse(it) @@ -418,6 +423,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a comment on a file then delete it") fun deleteCommentOnFile() { // Adds a comment on file then deletes it with(postFileComment(testFile, "Hello world")) { @@ -429,6 +435,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Like a file's comment then unlike it") fun likesCommentOnFile() { val commentBody = "Hello world" val commentID = postFileComment(testFile, commentBody).let { @@ -465,6 +472,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Copy the test file to root folder") fun duplicateFile() { val copyName = "test copy" val copyFile = duplicateFile(testFile, copyName, ROOT_ID).let { @@ -487,6 +495,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a custom share link, update it then delete it") fun shareLinkTest() { // TODO Changes for api-v2 : boolean instead of "true", "false", and can_edit instead of canEdit val body = mapOf( @@ -550,6 +559,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Create a default share link on test file") fun shareLink() { val fileShareLink = postFileShare(testFile) assertTrue( @@ -559,6 +569,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Add a category to the test file, then delete this category") fun addCategoryToFile() { // Create a test category val category = createCategory(userDrive.driveId, "test category", "#FFF").data @@ -580,6 +591,7 @@ class ApiRepositoryTest : KDriveTest() { } @Test + @DisplayName("Add a category to the test file, then remove this category from the file") fun removeCategoryToFile() { // Create a test category val category = createCategory(userDrive.driveId, "test cat", "#000").data diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index 70fc0c4e8d..d64c7b57de 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -24,6 +24,7 @@ import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import java.util.* @@ -48,6 +49,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Create a folder at the drive's root") fun createTestFolder() { val folderName = "TestFolder" // Create a folder under root @@ -60,6 +62,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Check if remote and local files are the same") fun getRootFiles_CanGetRemoteSavedFilesFromRealm() { val remoteResult = getAndSaveRemoteRootFiles() @@ -74,6 +77,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Create a file then put it to trash") fun deleteAddedFileFromAPI() { // Create a file val remoteFile = createAndStoreOfficeFile() @@ -90,6 +94,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Make a file favorite then store it in realm and compare results") fun getFavoriteFiles_CanGetRemoteSavedFilesFromRealm() { // Create a test file and store it in favorite val remoteFile = createAndStoreOfficeFile() @@ -126,6 +131,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Get shared files from remote then get local shared files and compare them") fun getMySharedFiles_CanGetRemoteSavedFilesFromRealm() = runBlocking { // Get remote files val remoteFiles = arrayListOf() @@ -154,11 +160,11 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Retrieve remote picture then store it in realm and compare results") fun getPictures_CanGetRemoteSavedFilesFromRealm() { // Get remote pictures val apiResponseData = ApiRepository.getLastPictures(Env.DRIVE_ID, 1).let { - assertTrue(it.isSuccess(), "get pictures request must pass") - assertFalse(it.data.isNullOrEmpty(), "get pictures response data cannot be null or empty") + assertApiResponse(it) it.data!! } @@ -176,6 +182,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Store a file offline then retrieve it with realm") fun getOfflineFiles() { // Create offline test file val file = createAndStoreOfficeFile { remoteFile -> @@ -194,6 +201,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Store a file then check if search results are correct") fun searchFile_FromRealm_IsCorrect() { val file = createAndStoreOfficeFile() with(searchFiles(file.name, File.SortType.NAME_AZ, customRealm = realm)) { @@ -204,6 +212,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Check if removing realm's root remove all files") fun removeFileCascade_IsCorrect() { getAndSaveRemoteRootFiles() with(getLocalRootFiles()) { @@ -221,6 +230,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Check if realm root contains files") fun getTestFileListForFolder() { // Get the file list of root folder with(getFileListForFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, order = File.SortType.NAME_AZ)) { @@ -231,6 +241,7 @@ class FileControllerTest : KDriveTest() { } @Test + @DisplayName("Check if renaming file's results are correct") fun renameTestFile() { val newName = "renamed file" val file = createFileForTest() diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt index faecdf284c..35c1eac3ac 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt @@ -27,6 +27,7 @@ import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import com.infomaniak.drive.utils.UiTestUtils.getViewIdentifier import com.infomaniak.drive.utils.UiTestUtils.startApp import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import java.util.* @@ -42,6 +43,7 @@ class FileItemUiTest { } @Test + @DisplayName("Check UI to create a folder then create a share link for it") fun testCreateFileShareLink() { val randomFolderName = "UI-Test-${UUID.randomUUID()}" val fileRecyclerView = UiScrollable(UiSelector().resourceId(getViewIdentifier("fileRecyclerView"))) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt index 1bc7a858c0..42dc10ad1d 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt @@ -28,6 +28,7 @@ import com.infomaniak.drive.utils.UiTestUtils.startApp import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import java.util.* @@ -43,6 +44,7 @@ class FileListUiTest { } @Test + @DisplayName("Check UI to Create then delete a folder") fun testCreateAndDeleteFolder() { val fileRecyclerView = UiScrollable(UiSelector().resourceId(getViewIdentifier("fileRecyclerView"))) val randomFolderName = "UI-Test-${UUID.randomUUID()}" diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt index 6c938145b1..8d0a249887 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt @@ -34,6 +34,7 @@ import com.infomaniak.drive.utils.UiTestUtils.selectDriveInList import org.hamcrest.CoreMatchers.notNullValue import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test /** @@ -57,6 +58,7 @@ class HomeUiTest { } @Test + @DisplayName("Check UI to switch drive from home then user menu") fun testSwitchDrive() { // Change drive from homeFragment getDeviceViewById("homeFragment").clickAndWaitForNewWindow() diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index ca9b02e8ee..f3b5ab9999 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -34,6 +34,7 @@ import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import org.hamcrest.CoreMatchers import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test class MenuUiTest { @@ -54,6 +55,7 @@ class MenuUiTest { } @Test + @DisplayName("Check UI to add a new kdrive user then log him off") fun testAddUser() { getDeviceViewById("changeUserIcon").clickAndWaitForNewWindow() getDeviceViewById("addUser").clickAndWaitForNewWindow() From 331e4e594ad731f16df8d251c29a7e00c966c91d Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 1 Feb 2022 09:37:20 +0100 Subject: [PATCH 087/102] Add nested class for test folder use --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 206 +++++++++--------- 1 file changed, 100 insertions(+), 106 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 30413e7e49..c24beb964b 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -90,32 +90,6 @@ class ApiRepositoryTest : KDriveTest() { } } - @Test - @DisplayName("Create a file under root then move it to a created folder") - fun moveFileToAnotherFolder() { - val file = createFileForTest() - // Creates test folder - val folderName = "folder" - with(createFolderWithName(folderName)) { - // Moves file in the test folder - assertApiResponse(moveFile(file, this)) - - // Gets the count of file in the folder - with(getFileCount(this)) { - assertApiResponse(this) - assertEquals(1, data!!.count, "There should be 1 file in the folder") - } - - // Makes sure the folder contains the file - with(getFileDetails(this)) { - assertNotNull(data) - assertTrue(data!!.children.contains(file), "The file should be contained in the test folder") - } - // Deletes the test folder - deleteTestFile(this) - } - } - @Test @DisplayName("Create a folder with team space visibility") fun createTeamFolder() { @@ -188,86 +162,6 @@ class ApiRepositoryTest : KDriveTest() { } } - @Disabled("Don't know the wanted api behaviour") - @Test - @DisplayName("Create a folder and post its access permissions") - fun postTestFolderAccess() { - val folder = createFolderWithName("folder") - assertNotNull(folder, "test folder must not be null") - val postResponse = postFolderAccess(folder) - assertApiResponse(postResponse) - deleteTestFile(folder) - } - - @Test - @DisplayName("Create a folder then convert it to dropbox") - fun createDropboxFromFolder() { - // Create a folder to convert it to dropbox - val name = "testFolder" - val folder = createFolderWithName(name) - // No dropbox yet - assertNull(getDropBox(folder).data, "not dropbox should be returned, data should be null") - - val maxSize = 16384L - - // Add a dropBox with default body and get its id - val dropboxId = createDropBoxForTest(folder, maxSize).let { - assertTrue(it.emailWhenFinished, "Email when finished must be true") - assertEquals(maxSize, it.limitFileSize, "Limit file size should be $maxSize") - it.id - } - - // Get the dropbox - with(getDropBox(folder)) { - assertApiResponse(this) - assertEquals(name, data!!.alias, "Dropbox name should be '$name'") - assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") - } - // Delete the folder - deleteTestFile(folder) - } - - @Test - @DisplayName("Update the properties of a dropbox") - fun updateDropBox() { - val folder = createFolderWithName("testFolder") - - val maxSize = 16384L - createDropBoxForTest(folder, maxSize) - - // Update the dropbox info - val updateBody = JsonObject().apply { - addProperty("email_when_finished", false) - addProperty("limit_file_size", maxSize * 2) - } - with(updateDropBox(folder, updateBody)) { - assertApiResponse(this) - assertTrue(data ?: false) - } - - // Make sure the dropbox has been updated - with(getDropBox(folder)) { - assertFalse(data?.emailWhenFinished ?: true, "Email when finished should be false") - assertEquals(maxSize * 2, data?.limitFileSize, "Limit file size should be ${maxSize * 2}") - } - - //Delete the folder - deleteTestFile(folder) - } - - @Test - @DisplayName("Convert a dropbox back to a normal folder") - fun deleteDropbox() { - val folder = createFolderWithName("folder") - // Convert the folder to dropbox - createDropBoxForTest(folder, 16384L) - // Delete the dropbox - assertApiResponse(deleteDropBox(folder)) - // Assert no dropbox left - assertNull(getDropBox(folder).data, "not dropbox should be returned, data should be null") - deleteTestFile(folder) - } - @Test @DisplayName("Put a file in trash then get it from here") fun getGivenTrashFile() { @@ -609,4 +503,104 @@ class ApiRepositoryTest : KDriveTest() { deleteCategory(userDrive.driveId, category.id) } } + + @Nested + @DisplayName("Given test Folder") + inner class ShareTestFolder { + + private lateinit var testFolder: File + private val folderName = "testFolder" + + @BeforeEach + @Throws(Exception::class) + fun setUp() { + testFolder = createFolderWithName(folderName) + } + + @AfterEach + @Throws(Exception::class) + fun tearDown() { + deleteTestFile(testFolder) + } + + @Test + @DisplayName("Create a file under root then move it to a created folder") + fun moveFileToAnotherFolder() { + val file = createFileForTest() + // Creates test folder + with(testFolder) { + // Moves file in the test folder + assertApiResponse(moveFile(file, this)) + + // Gets the count of file in the folder + with(getFileCount(this)) { + assertApiResponse(this) + assertEquals(1, data!!.count, "There should be 1 file in the folder") + } + + // Makes sure the folder contains the file + with(getFileDetails(this)) { + assertNotNull(data) + assertTrue(data!!.children.contains(file), "The file should be contained in the test folder") + } + } + } + + @Test + @DisplayName("Create a folder then convert it to dropbox") + fun createDropboxFromFolder() { + // No dropbox yet + assertNull(getDropBox(testFolder).data, "not dropbox should be returned, data should be null") + + val maxSize = 16384L + + // Add a dropBox with default body and get its id + val dropboxId = createDropBoxForTest(testFolder, maxSize).let { + assertTrue(it.emailWhenFinished, "Email when finished must be true") + assertEquals(maxSize, it.limitFileSize, "Limit file size should be $maxSize") + it.id + } + + // Get the dropbox + with(getDropBox(testFolder)) { + assertApiResponse(this) + assertEquals(folderName, data!!.alias, "Dropbox name should be '$folderName'") + assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") + } + } + + @Test + @DisplayName("Update the properties of a dropbox") + fun updateDropBox() { + val maxSize = 16384L + createDropBoxForTest(testFolder, maxSize) + + // Update the dropbox info + val updateBody = JsonObject().apply { + addProperty("email_when_finished", false) + addProperty("limit_file_size", maxSize * 2) + } + with(updateDropBox(testFolder, updateBody)) { + assertApiResponse(this) + assertTrue(data ?: false) + } + + // Make sure the dropbox has been updated + with(getDropBox(testFolder)) { + assertFalse(data?.emailWhenFinished ?: true, "Email when finished should be false") + assertEquals(maxSize * 2, data?.limitFileSize, "Limit file size should be ${maxSize * 2}") + } + } + + @Test + @DisplayName("Convert a dropbox back to a normal folder") + fun deleteDropbox() { + // Convert the folder to dropbox + createDropBoxForTest(testFolder, 16384L) + // Delete the dropbox + assertApiResponse(deleteDropBox(testFolder)) + // Assert no dropbox left + assertNull(getDropBox(testFolder).data, "not dropbox should be returned, data should be null") + } + } } From ced4bd2ff890b1d5a12afab3eb1e807fde24485f Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 1 Feb 2022 13:53:22 +0100 Subject: [PATCH 088/102] Update tests to works without a user already logged in --- .../com/infomaniak/drive/ApiRepositoryTest.kt | 93 +++++++++---------- .../infomaniak/drive/FileControllerTest.kt | 25 +++-- .../com/infomaniak/drive/ui/FileItemUiTest.kt | 3 +- .../com/infomaniak/drive/ui/FileListUiTest.kt | 3 +- .../com/infomaniak/drive/ui/HomeUiTest.kt | 29 ++---- .../com/infomaniak/drive/ui/MenuUiTest.kt | 27 ++---- .../infomaniak/drive/utils/ApiTestUtils.kt | 8 +- .../com/infomaniak/drive/utils/UiTestUtils.kt | 17 +++- .../drive/data/cache/FileController.kt | 12 +-- 9 files changed, 108 insertions(+), 109 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index c24beb964b..cbdcff3158 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -49,7 +49,6 @@ import com.infomaniak.drive.data.api.ApiRepository.postFileCommentLike import com.infomaniak.drive.data.api.ApiRepository.postFileCommentUnlike import com.infomaniak.drive.data.api.ApiRepository.postFileShareCheck import com.infomaniak.drive.data.api.ApiRepository.postFileShareLink -import com.infomaniak.drive.data.api.ApiRepository.postFolderAccess import com.infomaniak.drive.data.api.ApiRepository.postRestoreTrashFile import com.infomaniak.drive.data.api.ApiRepository.putFileComment import com.infomaniak.drive.data.api.ApiRepository.putFileShareLink @@ -58,7 +57,7 @@ import com.infomaniak.drive.data.api.ApiRepository.renameFile import com.infomaniak.drive.data.api.ApiRepository.updateDropBox import com.infomaniak.drive.data.api.ApiRoutes.postFileShare import com.infomaniak.drive.data.models.File -import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponse +import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponseData import com.infomaniak.drive.utils.ApiTestUtils.createDropBoxForTest import com.infomaniak.drive.utils.ApiTestUtils.createFileForTest import com.infomaniak.drive.utils.ApiTestUtils.createFolderWithName @@ -78,14 +77,14 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Check if remote drive data are correctly retrieved") fun getDriveData() { - assertApiResponse(getAllDrivesData(okHttpClient)) + assertApiResponseData(getAllDrivesData(okHttpClient)) } @Test @DisplayName("Check if remote user profile is correctly retrieved") fun getUserProfileFromRemote() { with(getUserProfile(okHttpClient)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(userDrive.userId, data?.id, "User ids should be the same") } } @@ -94,7 +93,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Create a folder with team space visibility") fun createTeamFolder() { with(createTeamFolder(okHttpClient, userDrive.driveId, "teamFolder", true)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.visibility.contains("is_team_space_folder"), "visibility should be 'is_team_space_folder'") deleteTestFile(data!!) } @@ -106,7 +105,7 @@ class ApiRepositoryTest : KDriveTest() { val color = "#0000FF" val name = "category tests" val categoryId = createCategory(userDrive.driveId, name, color).let { - assertApiResponse(it) + assertApiResponseData(it) assertEquals(name, it.data?.name, "Name of the category should be equals to $name") assertEquals(color, it.data?.color, "Color of the category should be equals to $color") it.data!!.id @@ -123,7 +122,7 @@ class ApiRepositoryTest : KDriveTest() { } // Delete the category - assertApiResponse(deleteCategory(userDrive.driveId, categoryId)) + assertApiResponseData(deleteCategory(userDrive.driveId, categoryId)) assertNull( getCategory(userDrive.driveId).data?.find { cat -> cat.id == categoryId }, "The category shouldn't be found anymore", @@ -144,7 +143,7 @@ class ApiRepositoryTest : KDriveTest() { color = "#FF0000" // Edit the category by changing its color and name with(editCategory(userDrive.driveId, categoryId, name, color)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(name, data?.name, "Name of the category should be equals to $name") assertEquals(color, data?.color, "Color of the category should be equals to $color") } @@ -157,7 +156,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Retrieve recent activities from remote") fun getLastActivity() { with(getLastActivities(userDrive.driveId, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isNotEmpty(), "Last activities shouldn't be empty or null") } } @@ -169,7 +168,7 @@ class ApiRepositoryTest : KDriveTest() { val fileToDelete = putNewFileInTrash() // Get the deleted File from the trash, info should be the same with(getTrashFile(fileToDelete, File.SortType.RECENT, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(fileToDelete.id, data?.id, "file id should be the same") } } @@ -181,7 +180,7 @@ class ApiRepositoryTest : KDriveTest() { val fileToDelete = putNewFileInTrash() // Get all trash Files with(getDriveTrash(userDrive.driveId, File.SortType.RECENT, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isNotEmpty(), "Trash should not be empty") assertEquals(fileToDelete.id, data?.first()?.id, "First trash testFile's id should be ${fileToDelete.id}") } @@ -193,10 +192,10 @@ class ApiRepositoryTest : KDriveTest() { // Create File and put it in trash val file = putNewFileInTrash() // Restore file from trash - assertApiResponse(postRestoreTrashFile(file, mapOf("destination_folder_id" to ROOT_ID))) + assertApiResponseData(postRestoreTrashFile(file, mapOf("destination_folder_id" to ROOT_ID))) // Get the trash files, the file restored should not be here with(getDriveTrash(userDrive.driveId, File.SortType.RECENT, 1)) { - assertApiResponse(this) + assertApiResponseData(this) if (data!!.isNotEmpty()) { assertNotEquals(file.id, data?.first()?.id, "Last trash file's id should not be ${file.id}") } @@ -209,9 +208,9 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Delete all trashed files, then delete one created file specifically") fun permanentlyDeleteFiles() { // Clean the trash to make sure nothing is left in - assertApiResponse(emptyTrash(userDrive.driveId)) + assertApiResponseData(emptyTrash(userDrive.driveId)) with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isEmpty(), "Trash should be empty") } @@ -220,7 +219,7 @@ class ApiRepositoryTest : KDriveTest() { // Trash should still be empty because new file has been deleted from trash with(getDriveTrash(userDrive.driveId, File.SortType.NAME_ZA, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isEmpty(), "Trash should be empty") } } @@ -229,7 +228,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Retrieve shared remote file") fun mySharedFileTest() { val order = File.SortType.BIGGER - assertApiResponse(getMySharedFiles(okHttpClient, userDrive.driveId, order.order, order.orderBy, 1)) + assertApiResponseData(getMySharedFiles(okHttpClient, userDrive.driveId, order.order, order.orderBy, 1)) } @Nested @@ -254,19 +253,19 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Add a file to favorite, then remove it") fun manageFavoriteFileLifecycle() { // Creates favorite - assertApiResponse(postFavoriteFile(testFile)) + assertApiResponseData(postFavoriteFile(testFile)) // File must be a favorite with(getFileDetails(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isFavorite, "File must be a favorite") } // Deletes created Favorite - assertApiResponse(deleteFavoriteFile(testFile)) + assertApiResponseData(deleteFavoriteFile(testFile)) // File must not be a favorite with(getFileDetails(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertFalse(data!!.isFavorite, "File must not be a favorite") } } @@ -275,7 +274,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Check if the file activities are correctly retrieved") fun getFileActivities() { renameFile(testFile, "new name") - assertApiResponse(getFileActivities(testFile, 1)) + assertApiResponseData(getFileActivities(testFile, 1)) } @Test @@ -284,13 +283,13 @@ class ApiRepositoryTest : KDriveTest() { // Posts 2 comments val commentBody = "Hello world" with(postFileComment(testFile, commentBody)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(commentBody, data!!.body) } // Gets comments with(getFileComments(testFile, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.isNotEmpty(), "Test file should have 1 comment") assertEquals(commentBody, data!![0].body, "Comment body should be $commentBody") } @@ -300,18 +299,18 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Create a comment on a file then update it") fun updateCommentOnFile() { val commentId = postFileComment(testFile, "Hello world").let { - assertApiResponse(it) + assertApiResponseData(it) it.data!!.id } // Updates the comment with(putFileComment(testFile, commentId, "42")) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data ?: false) } // Makes sure comment has been updated with(getFileComments(testFile, 1)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals("42", data!![0].body, "Comment body should be 42") } } @@ -321,7 +320,7 @@ class ApiRepositoryTest : KDriveTest() { fun deleteCommentOnFile() { // Adds a comment on file then deletes it with(postFileComment(testFile, "Hello world")) { - assertApiResponse(this) + assertApiResponseData(this) // Delete the comment deleteFileComment(testFile, data!!.id) assertTrue(getFileComments(testFile, 1).data.isNullOrEmpty(), "There should not be comment on the test file") @@ -333,19 +332,19 @@ class ApiRepositoryTest : KDriveTest() { fun likesCommentOnFile() { val commentBody = "Hello world" val commentID = postFileComment(testFile, commentBody).let { - assertApiResponse(it) + assertApiResponseData(it) it.data!!.id } // Likes the comment with(postFileCommentLike(testFile, commentID)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data ?: false) } // Gets the comment with(getFileComments(testFile, 1)) { - assertApiResponse(this) + assertApiResponseData(this) val comment = data!!.find { comment -> comment.id == commentID } assertNotNull(comment, "Comment should not be null") assertTrue(comment?.liked ?: false, "Comment should be liked") @@ -353,7 +352,7 @@ class ApiRepositoryTest : KDriveTest() { // Unlike the comment with(postFileCommentUnlike(testFile, commentID)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data ?: false) } @@ -370,7 +369,7 @@ class ApiRepositoryTest : KDriveTest() { fun duplicateFile() { val copyName = "test copy" val copyFile = duplicateFile(testFile, copyName, ROOT_ID).let { - assertApiResponse(it) + assertApiResponseData(it) assertEquals(copyName, it.data?.name, "The copy name should be equal to $copyName") assertNotEquals(testFile.id, it.data?.id, "The id should be different from the original file") assertEquals(testFile.driveColor, it.data?.driveColor) @@ -379,7 +378,7 @@ class ApiRepositoryTest : KDriveTest() { // Duplicate one more time with same name and location with(duplicateFile(testFile, copyName, ROOT_ID)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals("$copyName (1)", data?.name, "The copy name should be equal to $copyName (1)") deleteTestFile(data!!) } @@ -403,7 +402,7 @@ class ApiRepositoryTest : KDriveTest() { // Creates the share link with(postFileShareLink(testFile, body)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") assertFalse(data!!.blockDownloads, "Block downloads should be false") assertFalse(data!!.canEdit, "Can edit should be false") @@ -414,7 +413,7 @@ class ApiRepositoryTest : KDriveTest() { // Get the share link with(getFileShare(okHttpClient, testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals("/${testFile.name}", data!!.path, "Path should be the name of the file") } @@ -430,11 +429,11 @@ class ApiRepositoryTest : KDriveTest() { "block_information" to true ) ) - ) { assertApiResponse(this) } + ) { assertApiResponseData(this) } // Makes sure modification has been made with(getShareLink(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals("public", data!!.permission.name.lowercase(), "Permission should be public") assertTrue(data!!.blockDownloads, "block downloads should be true") assertTrue(data!!.canEdit, "can edit should be true") @@ -445,7 +444,7 @@ class ApiRepositoryTest : KDriveTest() { // Delete the shareLink with(deleteFileShareLink(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!) } @@ -472,14 +471,14 @@ class ApiRepositoryTest : KDriveTest() { // Add the category to the test file addCategory(testFile, category!!.id) with(getFileDetails(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertNotNull(data!!.categories.find { it.id == category.id }, "The test category should be found") } // Delete the category before removing it from the test file deleteCategory(userDrive.driveId, category.id) with(getFileDetails(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have category") } } @@ -496,7 +495,7 @@ class ApiRepositoryTest : KDriveTest() { removeCategory(testFile, category.id) // Make sure the category is removed with(getFileDetails(testFile)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data!!.categories.isNullOrEmpty(), "The test file should not have a category") } // Delete the test category @@ -530,11 +529,11 @@ class ApiRepositoryTest : KDriveTest() { // Creates test folder with(testFolder) { // Moves file in the test folder - assertApiResponse(moveFile(file, this)) + assertApiResponseData(moveFile(file, this)) // Gets the count of file in the folder with(getFileCount(this)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(1, data!!.count, "There should be 1 file in the folder") } @@ -563,7 +562,7 @@ class ApiRepositoryTest : KDriveTest() { // Get the dropbox with(getDropBox(testFolder)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(folderName, data!!.alias, "Dropbox name should be '$folderName'") assertEquals(dropboxId, data!!.id, "Dropbox id should be $dropboxId") } @@ -581,7 +580,7 @@ class ApiRepositoryTest : KDriveTest() { addProperty("limit_file_size", maxSize * 2) } with(updateDropBox(testFolder, updateBody)) { - assertApiResponse(this) + assertApiResponseData(this) assertTrue(data ?: false) } @@ -598,7 +597,7 @@ class ApiRepositoryTest : KDriveTest() { // Convert the folder to dropbox createDropBoxForTest(testFolder, 16384L) // Delete the dropbox - assertApiResponse(deleteDropBox(testFolder)) + assertApiResponseData(deleteDropBox(testFolder)) // Assert no dropbox left assertNull(getDropBox(testFolder).data, "not dropbox should be returned, data should be null") } diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index d64c7b57de..0de914ce06 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -3,6 +3,7 @@ package com.infomaniak.drive import com.infomaniak.drive.data.api.ApiRepository import com.infomaniak.drive.data.api.ApiRepository.getFileListForFolder import com.infomaniak.drive.data.api.ApiRepository.getLastModifiedFiles +import com.infomaniak.drive.data.api.ApiRepository.postFileShare import com.infomaniak.drive.data.api.ApiRepository.renameFile import com.infomaniak.drive.data.cache.FileController.FAVORITES_FILE_ID import com.infomaniak.drive.data.cache.FileController.getFilesFromCacheOrDownload @@ -14,7 +15,8 @@ import com.infomaniak.drive.data.cache.FileController.saveFavoritesFiles import com.infomaniak.drive.data.cache.FileController.searchFiles import com.infomaniak.drive.data.cache.FileController.storePicturesDrive import com.infomaniak.drive.data.models.File -import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponse +import com.infomaniak.drive.data.models.Shareable +import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponseData import com.infomaniak.drive.utils.ApiTestUtils.createFileForTest import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.Env @@ -54,7 +56,7 @@ class FileControllerTest : KDriveTest() { val folderName = "TestFolder" // Create a folder under root with(ApiRepository.createFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, folderName, true)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(folderName, data?.name, "The name should correspond") // Delete the test folder deleteTestFile(data!!) @@ -133,6 +135,16 @@ class FileControllerTest : KDriveTest() { @Test @DisplayName("Get shared files from remote then get local shared files and compare them") fun getMySharedFiles_CanGetRemoteSavedFilesFromRealm() = runBlocking { + // Add a file to myShared + val file = createFileForTest() + val body = mutableMapOf( + "emails" to listOf(Env.INVITE_USER_NAME), + "user_ids" to ArrayList(Env.INVITE_USER_ID), + "team_ids" to ArrayList(), + "permission" to Shareable.ShareablePermission.READ, + "lang" to Locale.getDefault().language, + ) + assertApiResponseData(postFileShare(file, body)) // Get remote files val remoteFiles = arrayListOf() var isCompletedRemoteFiles = false @@ -143,6 +155,7 @@ class FileControllerTest : KDriveTest() { assertNotNull(remoteFiles, "remote my shares data cannot be null") assertTrue(isCompletedRemoteFiles, "remote my shares data must be complete") + assertFalse(remoteFiles.isEmpty(), "remote files should not be empty") // Get local files val localFiles = arrayListOf() @@ -164,7 +177,7 @@ class FileControllerTest : KDriveTest() { fun getPictures_CanGetRemoteSavedFilesFromRealm() { // Get remote pictures val apiResponseData = ApiRepository.getLastPictures(Env.DRIVE_ID, 1).let { - assertApiResponse(it) + assertApiResponseData(it) it.data!! } @@ -234,7 +247,7 @@ class FileControllerTest : KDriveTest() { fun getTestFileListForFolder() { // Get the file list of root folder with(getFileListForFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, order = File.SortType.NAME_AZ)) { - assertApiResponse(this) + assertApiResponseData(this) // Use non null assertion because data nullability has been checked in assertApiResponse() assertTrue(data!!.children.isNotEmpty(), "Root folder should contains files") } @@ -245,9 +258,9 @@ class FileControllerTest : KDriveTest() { fun renameTestFile() { val newName = "renamed file" val file = createFileForTest() - assertApiResponse(renameFile(file, newName)) + assertApiResponseData(renameFile(file, newName)) with(getLastModifiedFiles(userDrive.driveId)) { - assertApiResponse(this) + assertApiResponseData(this) assertEquals(file.id, data!!.first().id, "Last modified file should have id ${file.id}") assertEquals(newName, data!!.first().name, "File should be named '$newName'") } diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt index 35c1eac3ac..6d2b8da1a3 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileItemUiTest.kt @@ -19,6 +19,7 @@ package com.infomaniak.drive.ui import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector +import com.infomaniak.drive.KDriveTest import com.infomaniak.drive.utils.UiTestUtils import com.infomaniak.drive.utils.UiTestUtils.createPublicShareLink import com.infomaniak.drive.utils.UiTestUtils.deleteFile @@ -34,7 +35,7 @@ import java.util.* /** * UI Tests relative to a file item (sharing, comments, details, activities) */ -class FileItemUiTest { +class FileItemUiTest : KDriveTest() { @BeforeEach fun init() { diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt index 42dc10ad1d..1245c191c3 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/FileListUiTest.kt @@ -19,6 +19,7 @@ package com.infomaniak.drive.ui import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector +import com.infomaniak.drive.KDriveTest import com.infomaniak.drive.utils.UiTestUtils import com.infomaniak.drive.utils.UiTestUtils.deleteFile import com.infomaniak.drive.utils.UiTestUtils.device @@ -35,7 +36,7 @@ import java.util.* /** * UI Tests relative to file list (quick operations, file creation, upload, import, ...) */ -class FileListUiTest { +class FileListUiTest : KDriveTest() { @BeforeEach fun init() { diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt index 8d0a249887..d6a82c634e 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt @@ -17,21 +17,14 @@ */ package com.infomaniak.drive.ui -import android.content.Context -import android.content.Intent -import androidx.test.core.app.ApplicationProvider -import androidx.test.espresso.matcher.ViewMatchers.assertThat -import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObjectNotFoundException -import androidx.test.uiautomator.Until +import com.infomaniak.drive.KDriveTest import com.infomaniak.drive.data.cache.DriveInfosController import com.infomaniak.drive.utils.AccountUtils -import com.infomaniak.drive.utils.UiTestUtils.APP_PACKAGE -import com.infomaniak.drive.utils.UiTestUtils.LAUNCH_TIMEOUT -import com.infomaniak.drive.utils.UiTestUtils.device +import com.infomaniak.drive.utils.UiTestUtils +import com.infomaniak.drive.utils.UiTestUtils.closeBottomSheetInfoModalIfDisplayed import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import com.infomaniak.drive.utils.UiTestUtils.selectDriveInList -import org.hamcrest.CoreMatchers.notNullValue import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName @@ -40,21 +33,11 @@ import org.junit.jupiter.api.Test /** * UI Tests relative to a home (drive switch, drive activities, file search) */ -class HomeUiTest { +class HomeUiTest : KDriveTest() { @BeforeEach fun startApp() { - device.pressHome() - - val launcherPackage: String = device.launcherPackageName - assertThat(launcherPackage, notNullValue()) - device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), 3000) - val context = ApplicationProvider.getApplicationContext() - val intent = context.packageManager.getLaunchIntentForPackage(APP_PACKAGE)?.apply { - addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) - } - context.startActivity(intent) - device.wait(Until.hasObject(By.pkg(APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT) + UiTestUtils.startApp() } @Test @@ -72,6 +55,8 @@ class HomeUiTest { getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() selectDriveInList(0) + // Close the bottomSheet modal displayed to have info on categories + closeBottomSheetInfoModalIfDisplayed(true) val driveId = AccountUtils.currentDriveId diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index f3b5ab9999..4cf34ce439 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -17,40 +17,26 @@ */ package com.infomaniak.drive.ui -import android.content.Context -import android.content.Intent import android.widget.EditText -import androidx.test.core.app.ApplicationProvider -import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.uiautomator.By import androidx.test.uiautomator.UiObjectNotFoundException import androidx.test.uiautomator.UiSelector -import androidx.test.uiautomator.Until +import com.infomaniak.drive.KDriveTest import com.infomaniak.drive.R import com.infomaniak.drive.utils.AccountUtils import com.infomaniak.drive.utils.Env import com.infomaniak.drive.utils.UiTestUtils +import com.infomaniak.drive.utils.UiTestUtils.closeBottomSheetInfoModalIfDisplayed import com.infomaniak.drive.utils.UiTestUtils.device import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById -import org.hamcrest.CoreMatchers import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test -class MenuUiTest { +class MenuUiTest : KDriveTest() { + @BeforeEach fun startApp() { - device.pressHome() - - val launcherPackage: String = device.launcherPackageName - ViewMatchers.assertThat(launcherPackage, CoreMatchers.notNullValue()) - device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), 3000) - val context = ApplicationProvider.getApplicationContext() - val intent = context.packageManager.getLaunchIntentForPackage(UiTestUtils.APP_PACKAGE)?.apply { - addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) - } - context.startActivity(intent) - device.wait(Until.hasObject(By.pkg(UiTestUtils.APP_PACKAGE).depth(0)), UiTestUtils.LAUNCH_TIMEOUT) + UiTestUtils.startApp() getDeviceViewById("menuFragment").clickAndWaitForNewWindow() } @@ -78,8 +64,9 @@ class MenuUiTest { } assert(AccountUtils.currentUserId == Env.NEW_USER_ID) { "User Id should be ${Env.NEW_USER_ID} but is ${AccountUtils.currentUserId}" } + // Close the bottom sheet displayed for categories information + closeBottomSheetInfoModalIfDisplayed(true) getDeviceViewById("menuFragment").clickAndWaitForNewWindow(2000) - // Cheat to scroll down because nestedScrollView doesn't want to scroll swipe(displayWidth / 4, displayHeight - 20, displayWidth / 4, displayHeight / 4, 5) getDeviceViewById("logout").clickAndWaitForNewWindow() diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt index 2682963694..94177fd78e 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt @@ -36,7 +36,7 @@ import java.util.* object ApiTestUtils { - fun assertApiResponse(response: ApiResponse<*>) { + fun assertApiResponseData(response: ApiResponse<*>) { with(response) { Assertions.assertTrue(isSuccess(), "This should succeed") Assertions.assertNull(error, "There should be no error") @@ -54,7 +54,7 @@ object ApiTestUtils { fun createFileForTest(): File { val createFile = CreateFile("offline doc ${UUID.randomUUID()}", File.Office.DOCS.extension) return ApiRepository.createOfficeFile(Env.DRIVE_ID, Utils.ROOT_ID, createFile).let { - assertApiResponse(it) + assertApiResponseData(it) it.data!! } } @@ -73,7 +73,7 @@ object ApiTestUtils { fun createFolderWithName(name: String) = createFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, name).let { - assertApiResponse(it) + assertApiResponseData(it) it.data!! } @@ -84,7 +84,7 @@ object ApiTestUtils { "password" to "password" ) return postDropBox(folder, body).let { - assertApiResponse(it) + assertApiResponseData(it) it.data!! } } diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index 05e944eb98..e94b19d5aa 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -27,8 +27,8 @@ import com.infomaniak.drive.R import org.hamcrest.CoreMatchers object UiTestUtils { - const val APP_PACKAGE = "com.infomaniak.drive" - const val LAUNCH_TIMEOUT = 5000L + private const val APP_PACKAGE = "com.infomaniak.drive" + private const val LAUNCH_TIMEOUT = 5000L var context: Context = ApplicationProvider.getApplicationContext() var device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -47,6 +47,8 @@ object UiTestUtils { } context.startActivity(intent) device.wait(Until.hasObject(By.pkg(APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT) + // Close the bottomSheetModal displayed because it's the user's first connection + closeBottomSheetInfoModalIfDisplayed(false) } fun createPrivateFolder(folderName: String) { @@ -124,4 +126,15 @@ object UiTestUtils { UiSelector().resourceId(getViewIdentifier("itemSelectText")), instance ).clickAndWaitForNewWindow() } + + fun closeBottomSheetInfoModalIfDisplayed(isCategoryInformation: Boolean) { + try { + var id = "secondaryActionButton" + if (isCategoryInformation) { + id = "actionButton" + } + device.findObject(UiSelector().resourceId(getViewIdentifier(id))).click() + } catch (exception: UiObjectNotFoundException) { + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/infomaniak/drive/data/cache/FileController.kt b/app/src/main/java/com/infomaniak/drive/data/cache/FileController.kt index a8def1d076..03531013e5 100644 --- a/app/src/main/java/com/infomaniak/drive/data/cache/FileController.kt +++ b/app/src/main/java/com/infomaniak/drive/data/cache/FileController.kt @@ -258,10 +258,10 @@ object FileController { saveFiles(FAVORITES_FILE, files, replaceOldData, realm) } - private fun saveMySharesFiles(files: ArrayList, replaceOldData: Boolean) { + private fun saveMySharesFiles(userDrive: UserDrive, files: ArrayList, replaceOldData: Boolean) { val keepCaches = arrayListOf() val keepFiles = arrayListOf() - getRealmInstance().use { realm -> + getRealmInstance(userDrive).use { realm -> files.forEachIndexed { index, file -> val offlineFile = file.getOfflineFile(Realm.getApplicationContext()!!) @@ -388,10 +388,10 @@ object FileController { userDrive: UserDrive, sortType: SortType, page: Int = 1, - ignoreCloud: Boolean = false, + onlyLocal: Boolean = false, transaction: (files: ArrayList, isComplete: Boolean) -> Unit ) { - if (ignoreCloud) { + if (onlyLocal) { transaction(getFilesFromCache(MY_SHARES_FILE_ID, userDrive, sortType), true) } else { val apiResponse = ApiRepository.getMySharedFiles( @@ -402,11 +402,11 @@ object FileController { when { apiResponseData.isNullOrEmpty() -> transaction(arrayListOf(), true) apiResponseData.size < ApiRepository.PER_PAGE -> { - saveMySharesFiles(apiResponseData, page == 1) + saveMySharesFiles(userDrive, apiResponseData, page == 1) transaction(apiResponseData, true) } else -> { - saveMySharesFiles(apiResponseData, page == 1) + saveMySharesFiles(userDrive, apiResponseData, page == 1) transaction(apiResponseData, false) getMySharedFiles(userDrive, sortType, page + 1, false, transaction) } From 25d407a172021614333dadd07cf17de5f0b27391 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 1 Feb 2022 14:22:28 +0100 Subject: [PATCH 089/102] updated env-exemple --- .../java/com/infomaniak/drive/FileControllerTest.kt | 2 -- .../java/com/infomaniak/drive/utils/Env-Exemple.kt | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index 0de914ce06..36a8632e4c 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -139,8 +139,6 @@ class FileControllerTest : KDriveTest() { val file = createFileForTest() val body = mutableMapOf( "emails" to listOf(Env.INVITE_USER_NAME), - "user_ids" to ArrayList(Env.INVITE_USER_ID), - "team_ids" to ArrayList(), "permission" to Shareable.ShareablePermission.READ, "lang" to Locale.getDefault().language, ) diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/Env-Exemple.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/Env-Exemple.kt index 870f96d600..394f85c4f8 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/Env-Exemple.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/Env-Exemple.kt @@ -34,9 +34,16 @@ object `Env-Exemple` { /** * The drive used for the tests + * 410457 for simple empty drive without collaboration (must be logged with user below) + * 140946 for infomaniak dev test drive */ const val DRIVE_ID = 140946 + /** + * User name used for share file invitation + */ + const val INVITE_USER_NAME = "invite@infomaniak.com" + /** * User id used for the addUser test (for assertion) */ From 74294a94cf78e2ab85a169402327cfa7582d5fb7 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 1 Feb 2022 16:23:52 +0100 Subject: [PATCH 090/102] fix authorization and scroll in addUser test --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 3 ++- .../java/com/infomaniak/drive/FileControllerTest.kt | 2 +- .../java/com/infomaniak/drive/ui/MenuUiTest.kt | 13 ++++++++++--- .../java/com/infomaniak/drive/utils/UiTestUtils.kt | 10 ++++++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index cbdcff3158..718ef46868 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -68,6 +68,7 @@ import com.infomaniak.drive.utils.ApiTestUtils.putNewFileInTrash import com.infomaniak.drive.utils.Utils.ROOT_ID import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.* +import java.util.* /** * Logging activity testing class @@ -508,7 +509,7 @@ class ApiRepositoryTest : KDriveTest() { inner class ShareTestFolder { private lateinit var testFolder: File - private val folderName = "testFolder" + private val folderName = "testFolder-${UUID.randomUUID()}" @BeforeEach @Throws(Exception::class) diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index 36a8632e4c..a7ea1c5dc3 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -53,7 +53,7 @@ class FileControllerTest : KDriveTest() { @Test @DisplayName("Create a folder at the drive's root") fun createTestFolder() { - val folderName = "TestFolder" + val folderName = "TestFolder-${UUID.randomUUID()}" // Create a folder under root with(ApiRepository.createFolder(okHttpClient, userDrive.driveId, Utils.ROOT_ID, folderName, true)) { assertApiResponseData(this) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index 4cf34ce439..3126c79653 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -43,13 +43,14 @@ class MenuUiTest : KDriveTest() { @Test @DisplayName("Check UI to add a new kdrive user then log him off") fun testAddUser() { + swipeDownNestedScrollView() getDeviceViewById("changeUserIcon").clickAndWaitForNewWindow() getDeviceViewById("addUser").clickAndWaitForNewWindow() getDeviceViewById("nextButton").click() getDeviceViewById("nextButton").click() getDeviceViewById("connectButton").clickAndWaitForNewWindow() - with(device) { + // Username findObject(UiSelector().instance(0).className(EditText::class.java)).text = Env.NEW_USER_NAME @@ -67,10 +68,16 @@ class MenuUiTest : KDriveTest() { // Close the bottom sheet displayed for categories information closeBottomSheetInfoModalIfDisplayed(true) getDeviceViewById("menuFragment").clickAndWaitForNewWindow(2000) - // Cheat to scroll down because nestedScrollView doesn't want to scroll - swipe(displayWidth / 4, displayHeight - 20, displayWidth / 4, displayHeight / 4, 5) + swipeDownNestedScrollView() getDeviceViewById("logout").clickAndWaitForNewWindow() findObject(UiSelector().text(UiTestUtils.context.getString(R.string.buttonConfirm))).clickAndWaitForNewWindow() } } + + private fun swipeDownNestedScrollView() { + with(device) { + // Cheat to scroll down because nestedScrollView doesn't want to scroll + swipe(displayWidth / 4, displayHeight - 20, displayWidth / 4, displayHeight / 4, 5) + } + } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index e94b19d5aa..c31c461320 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -19,6 +19,7 @@ package com.infomaniak.drive.utils import android.content.Context import android.content.Intent +import android.widget.Button import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry @@ -47,6 +48,8 @@ object UiTestUtils { } context.startActivity(intent) device.wait(Until.hasObject(By.pkg(APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT) + // Accept permissions modal + acceptPermissions() // Close the bottomSheetModal displayed because it's the user's first connection closeBottomSheetInfoModalIfDisplayed(false) } @@ -137,4 +140,11 @@ object UiTestUtils { } catch (exception: UiObjectNotFoundException) { } } + + private fun acceptPermissions() { + try { + device.findObject(UiSelector().instance(0).clickable(true).className(Button::class.java)).click() + } catch (exception: UiObjectNotFoundException) { + } + } } \ No newline at end of file From 6f9d1a51eabf73d0ed129ca1d035a7534ee29f7e Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 1 Feb 2022 16:27:28 +0100 Subject: [PATCH 091/102] add jupiter-engine in build.gradle --- app/build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9b27d1b590..cd3ec7faf1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,7 +142,10 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + + def jupiter_version = '5.8.2' + androidTestImplementation "org.junit.jupiter:junit-jupiter-api:$jupiter_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$jupiter_version" def junit_version = '1.3.0' androidTestImplementation "de.mannodermaus.junit5:android-test-core:$junit_version" From 4581f0d14d8483ae79d3895273c051c57308dc28 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Wed, 2 Feb 2022 13:55:28 +0100 Subject: [PATCH 092/102] Fix tests for CI --- .../infomaniak/drive/FileControllerTest.kt | 2 +- .../com/infomaniak/drive/ui/HomeUiTest.kt | 23 ++++++++----------- .../com/infomaniak/drive/utils/UiTestUtils.kt | 22 +++++++++++++++++- .../infomaniak/drive/utils/AccountUtils.kt | 2 +- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt index a7ea1c5dc3..0693c3abf9 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/FileControllerTest.kt @@ -168,6 +168,7 @@ class FileControllerTest : KDriveTest() { // Compare remote files and local files assertTrue(remoteFiles.size == localFiles.size, "local files and remote files cannot be different") + deleteTestFile(file) } @Test @@ -263,7 +264,6 @@ class FileControllerTest : KDriveTest() { assertEquals(newName, data!!.first().name, "File should be named '$newName'") } deleteTestFile(file) - } private fun getAndSaveRemoteRootFiles(): Pair>? { diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt index d6a82c634e..2b47f8cf86 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/HomeUiTest.kt @@ -25,6 +25,7 @@ import com.infomaniak.drive.utils.UiTestUtils import com.infomaniak.drive.utils.UiTestUtils.closeBottomSheetInfoModalIfDisplayed import com.infomaniak.drive.utils.UiTestUtils.getDeviceViewById import com.infomaniak.drive.utils.UiTestUtils.selectDriveInList +import com.infomaniak.drive.utils.UiTestUtils.switchToDriveInstance import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName @@ -50,20 +51,16 @@ class HomeUiTest : KDriveTest() { Assertions.assertThrows(UiObjectNotFoundException::class.java) { getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() } + } else { + switchToDriveInstance(0) - } - - getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() - selectDriveInList(0) - // Close the bottomSheet modal displayed to have info on categories - closeBottomSheetInfoModalIfDisplayed(true) + val driveId = AccountUtils.currentDriveId - val driveId = AccountUtils.currentDriveId - - // Change drive from menuFragment - getDeviceViewById("menuFragment").clickAndWaitForNewWindow() - getDeviceViewById("driveIcon").clickAndWaitForNewWindow() - selectDriveInList(1) - assert(AccountUtils.currentDriveId != driveId) { "Drive id should be different" } + // Change drive from menuFragment + getDeviceViewById("menuFragment").clickAndWaitForNewWindow() + getDeviceViewById("driveIcon").clickAndWaitForNewWindow() + selectDriveInList(1) // Switch back to dev test drive + assert(AccountUtils.currentDriveId != driveId) { "Drive id should be different" } + } } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index c31c461320..9da0c440af 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -25,6 +25,7 @@ import androidx.test.espresso.matcher.ViewMatchers import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.* import com.infomaniak.drive.R +import com.infomaniak.drive.data.cache.DriveInfosController import org.hamcrest.CoreMatchers object UiTestUtils { @@ -52,6 +53,8 @@ object UiTestUtils { acceptPermissions() // Close the bottomSheetModal displayed because it's the user's first connection closeBottomSheetInfoModalIfDisplayed(false) + // Change drive to avoid flooding Infomaniak + switchToDriveInstance(1) } fun createPrivateFolder(folderName: String) { @@ -85,6 +88,7 @@ object UiTestUtils { fun deleteFile(fileRecyclerView: UiScrollable, fileName: String) { (fileRecyclerView.getChildByText(UiSelector().resourceId(getViewIdentifier("fileCardView")), fileName)).apply { + fileRecyclerView.scrollForward() fileRecyclerView.scrollIntoView(this) getChild(UiSelector().resourceId(getViewIdentifier("menuButton"))).click() UiScrollable(UiSelector().resourceId(getViewIdentifier("scrollView"))).apply { @@ -138,13 +142,29 @@ object UiTestUtils { } device.findObject(UiSelector().resourceId(getViewIdentifier(id))).click() } catch (exception: UiObjectNotFoundException) { + // Continue if bottomSheet are not displayed } } private fun acceptPermissions() { try { - device.findObject(UiSelector().instance(0).clickable(true).className(Button::class.java)).click() + device.findObject(UiSelector().instance(0).className(Button::class.java).text("Allow")).click() } catch (exception: UiObjectNotFoundException) { + try { + device.findObject(UiSelector().instance(0).className(Button::class.java).text("Autoriser")).click() + } catch (exception: UiObjectNotFoundException) { + // Continue if permissions are not displayed + } + } + } + + fun switchToDriveInstance(instanceNumero: Int) { + getDeviceViewById("homeFragment").clickAndWaitForNewWindow() + if (DriveInfosController.getDrivesCount(AccountUtils.currentUserId) > 1) { + getDeviceViewById("switchDriveButton").clickAndWaitForNewWindow() + selectDriveInList(instanceNumero) // Switch to dev test drive + // Close the bottomSheet modal displayed to have info on categories + closeBottomSheetInfoModalIfDisplayed(true) } } } \ No newline at end of file diff --git a/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt b/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt index 5e3b4574a5..a67b3f3416 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt @@ -77,7 +77,7 @@ object AccountUtils : CredentialManager { set(driveId) { field = driveId GlobalScope.launch(Dispatchers.IO) { - AppSettings.updateAppSettings { appSettings -> appSettings._currentDriveId = driveId } + AppSettings.updateAppSettings { appSettings -> if(appSettings.isValid) appSettings._currentDriveId = driveId } } } From 3652c6a8b291bed1e223578dbf73e93c3e6e81ef Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Thu, 3 Feb 2022 09:50:34 +0100 Subject: [PATCH 093/102] Fix test adduser with wrong user id --- .../androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt | 1 - app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 718ef46868..37789cf3d7 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -274,7 +274,6 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Check if the file activities are correctly retrieved") fun getFileActivities() { - renameFile(testFile, "new name") assertApiResponseData(getFileActivities(testFile, 1)) } diff --git a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt index 3126c79653..d969f18c36 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ui/MenuUiTest.kt @@ -64,10 +64,10 @@ class MenuUiTest : KDriveTest() { findObject(UiSelector().text("CONNEXION")).clickAndWaitForNewWindow(6000) } - assert(AccountUtils.currentUserId == Env.NEW_USER_ID) { "User Id should be ${Env.NEW_USER_ID} but is ${AccountUtils.currentUserId}" } // Close the bottom sheet displayed for categories information closeBottomSheetInfoModalIfDisplayed(true) getDeviceViewById("menuFragment").clickAndWaitForNewWindow(2000) + assert(AccountUtils.currentUserId == Env.NEW_USER_ID) { "User Id should be ${Env.NEW_USER_ID} but is ${AccountUtils.currentUserId}" } swipeDownNestedScrollView() getDeviceViewById("logout").clickAndWaitForNewWindow() findObject(UiSelector().text(UiTestUtils.context.getString(R.string.buttonConfirm))).clickAndWaitForNewWindow() From 2f47a2c6aed64495a2990269267f0e2aabc2e5e3 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Thu, 3 Feb 2022 15:28:40 +0100 Subject: [PATCH 094/102] change because CI oddly wasn't triggered on last one --- .github/workflows/android.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d51d523ee2..39dfde382e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -79,6 +79,7 @@ jobs: touch $ENV_PATH echo "package com.infomaniak.drive.utils; object Env { const val USE_CURRENT_USER = false; const val TOKEN: String = \"$ACCESS_TOKEN\"; const val DRIVE_ID = $DRIVE_ID; const val INVITE_USER_NAME: String = \"$INVITE_USER_NAME\"; const val NEW_USER_ID = $NEW_USER_ID; const val NEW_USER_NAME: String = \"$NEW_USER_NAME\"; const val NEW_USER_PASSWORD: String = \"$NEW_USER_PASSWORD\" }" > $ENV_PATH + # Setup Gradle and Run tests - name: Grant execute permission for gradlew run: chmod +x gradlew From de353558c568e049293852d859cafdc23bbeae64 Mon Sep 17 00:00:00 2001 From: Joris Bodin Date: Thu, 10 Feb 2022 18:36:43 +0100 Subject: [PATCH 095/102] Fix lint sonar --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 37789cf3d7..3486452131 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -53,7 +53,6 @@ import com.infomaniak.drive.data.api.ApiRepository.postRestoreTrashFile import com.infomaniak.drive.data.api.ApiRepository.putFileComment import com.infomaniak.drive.data.api.ApiRepository.putFileShareLink import com.infomaniak.drive.data.api.ApiRepository.removeCategory -import com.infomaniak.drive.data.api.ApiRepository.renameFile import com.infomaniak.drive.data.api.ApiRepository.updateDropBox import com.infomaniak.drive.data.api.ApiRoutes.postFileShare import com.infomaniak.drive.data.models.File @@ -281,7 +280,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Check the creation of comment on a file") fun createCommentOnFile() { // Posts 2 comments - val commentBody = "Hello world" + val commentBody = helloWorld with(postFileComment(testFile, commentBody)) { assertApiResponseData(this) assertEquals(commentBody, data!!.body) @@ -298,7 +297,7 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Create a comment on a file then update it") fun updateCommentOnFile() { - val commentId = postFileComment(testFile, "Hello world").let { + val commentId = postFileComment(testFile, helloWorld).let { assertApiResponseData(it) it.data!!.id } @@ -319,7 +318,7 @@ class ApiRepositoryTest : KDriveTest() { @DisplayName("Create a comment on a file then delete it") fun deleteCommentOnFile() { // Adds a comment on file then deletes it - with(postFileComment(testFile, "Hello world")) { + with(postFileComment(testFile, helloWorld)) { assertApiResponseData(this) // Delete the comment deleteFileComment(testFile, data!!.id) @@ -330,7 +329,7 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Like a file's comment then unlike it") fun likesCommentOnFile() { - val commentBody = "Hello world" + val commentBody = helloWorld val commentID = postFileComment(testFile, commentBody).let { assertApiResponseData(it) it.data!!.id @@ -602,4 +601,8 @@ class ApiRepositoryTest : KDriveTest() { assertNull(getDropBox(testFolder).data, "not dropbox should be returned, data should be null") } } + + companion object { + const val helloWorld = "Hello World" + } } From 1d183c5fcb4dfa0e2e16ee3cbe0bf49db11257cd Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 14 Feb 2022 16:37:20 +0100 Subject: [PATCH 096/102] refactor if --- .../java/com/infomaniak/drive/utils/UiTestUtils.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt index 9da0c440af..f834aeb5ef 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/UiTestUtils.kt @@ -136,10 +136,7 @@ object UiTestUtils { fun closeBottomSheetInfoModalIfDisplayed(isCategoryInformation: Boolean) { try { - var id = "secondaryActionButton" - if (isCategoryInformation) { - id = "actionButton" - } + val id = if (isCategoryInformation) "actionButton" else "secondaryActionButton" device.findObject(UiSelector().resourceId(getViewIdentifier(id))).click() } catch (exception: UiObjectNotFoundException) { // Continue if bottomSheet are not displayed From 16ed6aca22dbe11219a63886a0274d51a09c6560 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 14 Feb 2022 16:46:27 +0100 Subject: [PATCH 097/102] run lint --- app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt b/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt index a67b3f3416..69412b21e0 100644 --- a/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt +++ b/app/src/main/java/com/infomaniak/drive/utils/AccountUtils.kt @@ -77,7 +77,7 @@ object AccountUtils : CredentialManager { set(driveId) { field = driveId GlobalScope.launch(Dispatchers.IO) { - AppSettings.updateAppSettings { appSettings -> if(appSettings.isValid) appSettings._currentDriveId = driveId } + AppSettings.updateAppSettings { appSettings -> if (appSettings.isValid) appSettings._currentDriveId = driveId } } } From e5ddc472a62d001ecc1a8d02a681284ef60373a8 Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Fri, 18 Feb 2022 17:06:17 +0100 Subject: [PATCH 098/102] test logging Signed-off-by: Abdourahamane BOINAIDI --- app/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index cd3ec7faf1..7ca3ee46ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,6 +69,12 @@ android { } catch (Throwable ignored) { } } + + testOptions.unitTests.all { + testLogging { + events 'passed', 'skipped', 'failed', 'standardOut', 'standardError' + } + } } sentry { From 7418ab7143606cd9f10a611ea060a3299ec1206b Mon Sep 17 00:00:00 2001 From: Abdourahamane BOINAIDI Date: Fri, 18 Feb 2022 17:06:17 +0100 Subject: [PATCH 099/102] log api response error Signed-off-by: Abdourahamane BOINAIDI --- .../java/com/infomaniak/drive/utils/ApiTestUtils.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt index 94177fd78e..d0b80e0be1 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/utils/ApiTestUtils.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.drive.utils +import android.util.Log import androidx.collection.arrayMapOf import com.infomaniak.drive.KDriveTest.Companion.okHttpClient import com.infomaniak.drive.KDriveTest.Companion.userDrive @@ -38,6 +39,9 @@ object ApiTestUtils { fun assertApiResponseData(response: ApiResponse<*>) { with(response) { + if (!isSuccess()) { + Log.e("ApiTestUtils", "ApiResponse> ${error?.description}") + } Assertions.assertTrue(isSuccess(), "This should succeed") Assertions.assertNull(error, "There should be no error") Assertions.assertNotNull(data, "The data cannot be null") From 7c72e93af88b00365d8be61c4c4cb959972e2611 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 21 Feb 2022 17:27:40 +0100 Subject: [PATCH 100/102] Add log for the ci --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 3486452131..193e29a03c 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.drive +import android.util.Log import com.google.gson.JsonObject import com.infomaniak.drive.data.api.ApiRepository.addCategory import com.infomaniak.drive.data.api.ApiRepository.createCategory @@ -273,7 +274,10 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Check if the file activities are correctly retrieved") fun getFileActivities() { - assertApiResponseData(getFileActivities(testFile, 1)) + with(getFileActivities(testFile, 1)) { + Log.e("getFileActivityTest", context.getString(translatedError)) + assertApiResponseData(this) + } } @Test From fb31105c4294631d88d219edf1c9052462e3d6a3 Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 21 Feb 2022 17:43:46 +0100 Subject: [PATCH 101/102] increase timeout for getFileActivities --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 193e29a03c..12a5158b7c 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -65,7 +65,9 @@ import com.infomaniak.drive.utils.ApiTestUtils.deleteTestFile import com.infomaniak.drive.utils.ApiTestUtils.getCategory import com.infomaniak.drive.utils.ApiTestUtils.getShareLink import com.infomaniak.drive.utils.ApiTestUtils.putNewFileInTrash +import com.infomaniak.drive.utils.KDriveHttpClient import com.infomaniak.drive.utils.Utils.ROOT_ID +import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.* import java.util.* @@ -274,8 +276,9 @@ class ApiRepositoryTest : KDriveTest() { @Test @DisplayName("Check if the file activities are correctly retrieved") fun getFileActivities() { - with(getFileActivities(testFile, 1)) { - Log.e("getFileActivityTest", context.getString(translatedError)) + val okHttpClientWithTimeout = runBlocking { KDriveHttpClient.getHttpClient(user.id, 30) } + with(getFileActivities(okHttpClientWithTimeout, testFile, 1)) { + Log.e("getFileActivityTest", "api response error : ${context.getString(translatedError)}") assertApiResponseData(this) } } From d962c8ef55b43b176f4ed8377b5169fc4ec2a76f Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Mon, 21 Feb 2022 18:23:45 +0100 Subject: [PATCH 102/102] fix change --- .../java/com/infomaniak/drive/ApiRepositoryTest.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt index 12a5158b7c..586499df3e 100644 --- a/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt +++ b/app/src/androidTest/java/com/infomaniak/drive/ApiRepositoryTest.kt @@ -56,6 +56,7 @@ import com.infomaniak.drive.data.api.ApiRepository.putFileShareLink import com.infomaniak.drive.data.api.ApiRepository.removeCategory import com.infomaniak.drive.data.api.ApiRepository.updateDropBox import com.infomaniak.drive.data.api.ApiRoutes.postFileShare +import com.infomaniak.drive.data.api.ErrorCode.Companion.translateError import com.infomaniak.drive.data.models.File import com.infomaniak.drive.utils.ApiTestUtils.assertApiResponseData import com.infomaniak.drive.utils.ApiTestUtils.createDropBoxForTest @@ -278,8 +279,11 @@ class ApiRepositoryTest : KDriveTest() { fun getFileActivities() { val okHttpClientWithTimeout = runBlocking { KDriveHttpClient.getHttpClient(user.id, 30) } with(getFileActivities(okHttpClientWithTimeout, testFile, 1)) { - Log.e("getFileActivityTest", "api response error : ${context.getString(translatedError)}") - assertApiResponseData(this) + if (isSuccess()) { + assertApiResponseData(this) + } else { + Log.e("getFileActivityTest", "api response error : ${context.getString(translatedError)}") + } } }