Skip to content

Commit

Permalink
Merge pull request #426 from Infomaniak/Folder-Colors
Browse files Browse the repository at this point in the history
Colored Folders
  • Loading branch information
sirambd authored Jan 31, 2022
2 parents ca046ac + 981bc0e commit 61868d7
Show file tree
Hide file tree
Showing 43 changed files with 863 additions and 166 deletions.
177 changes: 108 additions & 69 deletions .idea/navEditor.xml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ android {
versionName "4.1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

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/"'
buildConfigField 'String', 'INFOMANIAK_API', '"https://api.infomaniak.com/1/"'
buildConfigField 'String', 'OFFICE_URL', '"https://drive.infomaniak.com/app/office/"'
buildConfigField 'String', 'SHOP_URL', '"https://shop.infomaniak.com/order/"'
Expand Down Expand Up @@ -56,6 +58,11 @@ android {
fdroid {
dimension "distribution"
}
preprod {
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/"'
}
}

gradle.buildFinished { BuildResult buildResult ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ object ApiRepository {
"&actions[]=file_favorite_remove" +
"&actions[]=file_categorize" +
"&actions[]=file_uncategorize" +
"&actions[]=file_color_update" +
"&actions[]=file_color_delete" +
"&actions[]=share_link_create" +
"&actions[]=share_link_update" +
"&actions[]=share_link_delete" +
Expand Down Expand Up @@ -170,6 +172,10 @@ object ApiRepository {
return callApi(ApiRoutes.renameFile(file), POST, mapOf("name" to newName))
}

fun updateFolderColor(file: File, color: String): ApiResponse<Boolean> {
return callApi(ApiRoutes.updateFolderColor(file), POST, mapOf("color" to color))
}

fun duplicateFile(file: File, copyName: String?, folderId: Int): ApiResponse<File> {
val body = if (copyName == null) mapOf() else mapOf("name" to copyName)
return callApi(ApiRoutes.duplicateFile(file, folderId), POST, body)
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/infomaniak/drive/data/api/ApiRoutes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ object ApiRoutes {

private fun fileURL(file: File) = "${DRIVE_API}${file.driveId}/file/${file.id}"

private fun fileURLv2(file: File) = "${DRIVE_API_V2}${file.driveId}/files/${file.id}"

private fun trashURL(file: File) = "${DRIVE_API}${file.driveId}/file/trash/${file.id}"

fun getAllDrivesData() = "${DRIVE_API}init?with=drives,users,teams,ips,categories"
Expand Down Expand Up @@ -90,6 +92,8 @@ object ApiRoutes {

fun renameFile(file: File) = "${fileURL(file)}/rename"

fun updateFolderColor(file: File) = "${fileURLv2(file)}/color"

fun duplicateFile(file: File, folderId: Int) = "${fileURL(file)}/copy/$folderId?$with"

fun uploadFile(driveId: Int, folderId: Int) = "${DRIVE_API}$driveId/file/$folderId/upload"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ object FileController {
return apiResponse
}

fun updateFolderColor(file: File, color: String, realm: Realm? = null): ApiResponse<Boolean> {
return ApiRepository.updateFolderColor(file, color).also {
if (it.isSuccess()) updateFile(file.id, realm) { localFile -> localFile.color = color }
}
}

fun deleteFile(
file: File,
realm: Realm? = null,
Expand Down Expand Up @@ -785,9 +791,7 @@ object FileController {
FileActivityType.FILE_TRASH -> {
if (returnResponse[fileId] == null || returnResponse[fileId]?.createdAt?.time == createdAt.time) { // Api fix
getParentFile(fileId = fileId, realm = realm)?.let { parent ->
if (parent.id == currentFolder.id) {
removeFile(fileId, customRealm = realm, recursive = false)
}
if (parent.id == currentFolder.id) removeFile(fileId, customRealm = realm, recursive = false)
}
returnResponse[fileId] = this
}
Expand All @@ -814,6 +818,8 @@ object FileController {
FileActivityType.FILE_RENAME,
FileActivityType.FILE_CATEGORIZE,
FileActivityType.FILE_UNCATEGORIZE,
FileActivityType.FILE_COLOR_UPDATE,
FileActivityType.FILE_COLOR_DELETE,
FileActivityType.FILE_SHARE_CREATE,
FileActivityType.FILE_SHARE_DELETE,
FileActivityType.FILE_SHARE_UPDATE,
Expand Down
13 changes: 11 additions & 2 deletions app/src/main/java/com/infomaniak/drive/data/cache/FileMigration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import java.util.*

class FileMigration : RealmMigration {
companion object {
const val bddVersion = 2L // Must be bumped when the schema changes
const val bddVersion = 3L // Must be bumped when the schema changes
}

override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Expand Down Expand Up @@ -98,6 +98,15 @@ class FileMigration : RealmMigration {

oldVersionTemp++
}

// Migrated to version 3:
// - Added new field (Folder Color) in File table
if (oldVersionTemp == 2L) {
schema.get(File::class.java.simpleName)?.apply {
addField("_color", String::class.java)
}
oldVersionTemp++
}
}

override fun equals(other: Any?): Boolean {
Expand All @@ -109,4 +118,4 @@ class FileMigration : RealmMigration {
override fun hashCode(): Int {
return javaClass.hashCode()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum class BulkOperationType(@StringRes val title: Int, @PluralsRes val successM
TRASH(R.string.fileListDeletionInProgressSnackbar, R.plurals.snackbarMoveTrashConfirmation),
MOVE(R.string.fileListMoveInProgressSnackbar, R.plurals.fileListMoveFileConfirmationSnackbar),
COPY(R.string.fileListCopyInProgressSnackbar, R.plurals.fileListDuplicationConfirmationSnackbar),
COLOR_FOLDER(0, R.plurals.fileListColorFolderConfirmationSnackbar),

SET_OFFLINE(0, successMessage = R.plurals.fileListAddOfflineConfirmationSnackbar),
ADD_FAVORITES(0, successMessage = R.plurals.fileListAddFavorisConfirmationSnackbar);
Expand All @@ -44,4 +45,4 @@ enum class BulkOperationType(@StringRes val title: Int, @PluralsRes val successM
else -> context.copyOperationProgressNotification()
}
}
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/com/infomaniak/drive/data/models/File.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ open class File(
var children: @WriteWith<FileRealmListParceler> RealmList<File> = RealmList(),
@SerializedName("collaborative_folder")
var collaborativeFolder: String? = null,
@SerializedName("color")
private var _color: String? = null,
@SerializedName("converted_type")
var convertedType: String = "",
@SerializedName("created_at")
Expand Down Expand Up @@ -334,6 +336,19 @@ open class File(
}
}

fun isAllowedToBeColored(): Boolean {
return !isDisabled()
&& isFolder()
&& getVisibilityType() != VisibilityType.IS_SHARED_SPACE
&& getVisibilityType() != VisibilityType.IS_TEAM_SPACE
}

var color: String
get() = _color ?: "#9F9F9F" // R.color.secondaryText
set(color) {
_color = color
}

// For applyFileActivity in FileController
override fun equals(other: Any?): Boolean {
if (other is File) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ open class FileActivity(
FileActivityType.COLLABORATIVE_FOLDER_DELETE -> R.string.fileActivityCollaborativeFolderDelete
FileActivityType.FILE_CATEGORIZE -> R.string.fileDetailsActivityFileCategorize
FileActivityType.FILE_UNCATEGORIZE -> R.string.fileDetailsActivityFileUncategorize
FileActivityType.FILE_COLOR_UPDATE -> R.string.fileDetailsActivityFileColorUpdate
FileActivityType.FILE_COLOR_DELETE -> R.string.fileDetailsActivityFileColorDelete
}

enum class FileActivityType {
Expand All @@ -158,6 +160,8 @@ open class FileActivity(
FILE_SHARE_DELETE,
FILE_CATEGORIZE,
FILE_UNCATEGORIZE,
FILE_COLOR_UPDATE,
FILE_COLOR_DELETE,
SHARE_LINK_CREATE,
SHARE_LINK_UPDATE,
SHARE_LINK_DELETE,
Expand Down Expand Up @@ -191,4 +195,4 @@ open class FileActivity(
return if (action == "file_move") FileActivityType.FILE_MOVE_IN
else FileActivityType.valueOf(action.uppercase(Locale.ROOT))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,12 @@ open class Drive(
}
}

override fun hashCode(): Int {
return objectId.hashCode()
}
override fun hashCode(): Int = objectId.hashCode()

enum class DrivePack(val value: String) {
FREE("free"),
SOLO("solo"),
TEAM("team"),
PRO("pro")
PRO("pro"),
}

}
}
12 changes: 9 additions & 3 deletions app/src/main/java/com/infomaniak/drive/ui/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ class MainViewModel(appContext: Application) : AndroidViewModel(appContext) {

fun updateMultiSelectMediator(mediator: MediatorLiveData<Pair<Int, Int>>): (ApiResponse<*>) -> Unit = { apiResponse ->
val total = mediator.value!!.second + 1
mediator.value =
if (apiResponse.isSuccess()) mediator.value!!.first + 1 to total
else mediator.value!!.first to total
mediator.value = if (apiResponse.isSuccess()) {
mediator.value!!.first + 1 to total
} else {
mediator.value!!.first to total
}
}

fun postFileShareLink(
Expand Down Expand Up @@ -210,6 +212,10 @@ class MainViewModel(appContext: Application) : AndroidViewModel(appContext) {
emit(FileController.renameFile(file, newName))
}

fun updateFolderColor(file: File, color: String) = liveData(Dispatchers.IO) {
emit(FileController.updateFolderColor(file, color))
}

fun deleteFile(file: File, userDrive: UserDrive? = null, onSuccess: ((fileID: Int) -> Unit)? = null) =
liveData(Dispatchers.IO) {
emit(FileController.deleteFile(file, userDrive = userDrive, context = getContext(), onSuccess = onSuccess))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
import androidx.lifecycle.AndroidViewModel
Expand All @@ -32,6 +33,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.infomaniak.drive.R
import com.infomaniak.drive.data.api.ApiRepository
import com.infomaniak.drive.data.api.ApiRoutes
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.*
Expand All @@ -42,31 +44,62 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() {
private val actionMultiSelectModel by viewModels<ActionMultiSelectModel>()
private val navigationArgs: ActionMultiSelectBottomSheetDialogArgs by navArgs()

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_bottom_sheet_action_multi_select, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.fragment_bottom_sheet_action_multi_select, container, false)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addFavorites.setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) }
val otherActionsVisibility = navigationArgs.fileIds.size in 1..BulkOperationsUtils.MIN_SELECTED
configureColoredFolder(otherActionsVisibility)
configureAddFavorites(otherActionsVisibility)
configureAvailableOffline(otherActionsVisibility)
configureDownloadFile()
configureDuplicateFile()
}

availableOfflineSwitch.setOnCheckedChangeListener { _, _ -> onActionSelected(SelectDialogAction.OFFLINE) }
availableOffline.setOnClickListener { onActionSelected(SelectDialogAction.OFFLINE) }
duplicateFile.setOnClickListener { onActionSelected(SelectDialogAction.DUPLICATE) }
private fun configureColoredFolder(otherActionsVisibility: Boolean) {
disabledColoredFolder.isGone = computeColoredFolderAvailability(navigationArgs.fileIds)
coloredFolder.apply {
setOnClickListener { onActionSelected(SelectDialogAction.COLOR_FOLDER) }
isVisible = otherActionsVisibility
}
}

disabledAvailableOffline.isVisible = navigationArgs.onlyFolders
private fun configureAddFavorites(otherActionsVisibility: Boolean) {
addFavorites.apply {
setOnClickListener { onActionSelected(SelectDialogAction.ADD_FAVORITES) }
isVisible = otherActionsVisibility
}
}

val otherActionsVisibility = navigationArgs.fileIds.size in 1..BulkOperationsUtils.MIN_SELECTED
availableOffline.isVisible = otherActionsVisibility
addFavorites.isVisible = otherActionsVisibility
private fun configureAvailableOffline(otherActionsVisibility: Boolean) {
availableOfflineSwitch.setOnCheckedChangeListener { _, _ -> onActionSelected(SelectDialogAction.OFFLINE) }
disabledAvailableOffline.isVisible = navigationArgs.onlyFolders
availableOffline.apply {
setOnClickListener { onActionSelected(SelectDialogAction.OFFLINE) }
isVisible = otherActionsVisibility
}
}

private fun configureDownloadFile() {
val drivePermissions = DrivePermissions()
drivePermissions.registerPermissions(this) { authorized -> if (authorized) downloadFileArchive() }
downloadFile.setOnClickListener {
if (drivePermissions.checkWriteStoragePermission()) downloadFileArchive()
downloadFile.apply {
setOnClickListener { if (drivePermissions.checkWriteStoragePermission()) downloadFileArchive() }
isVisible = navigationArgs.fileIds.isNotEmpty()
}
}

private fun configureDuplicateFile() {
duplicateFile.setOnClickListener { onActionSelected(SelectDialogAction.DUPLICATE) }
}

private fun computeColoredFolderAvailability(fileIds: IntArray): Boolean {
fileIds.forEach {
val file = FileController.getFileById(it)
if (file?.isAllowedToBeColored() == true) return true
}
downloadFile.isVisible = navigationArgs.fileIds.isNotEmpty()
return false
}

private fun downloadFileArchive() {
Expand All @@ -88,11 +121,15 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() {
SelectDialogAction.ADD_FAVORITES -> BulkOperationType.ADD_FAVORITES
SelectDialogAction.OFFLINE -> BulkOperationType.SET_OFFLINE
SelectDialogAction.DUPLICATE -> BulkOperationType.COPY
SelectDialogAction.COLOR_FOLDER -> BulkOperationType.COLOR_FOLDER
else -> null
}

if (finalType == null) setBackNavigationResult(DISABLE_SELECT_MODE, true)
else setBackNavigationResult(SELECT_DIALOG_ACTION, finalType)
if (finalType == null) {
setBackNavigationResult(DISABLE_SELECT_MODE, true)
} else {
setBackNavigationResult(SELECT_DIALOG_ACTION, finalType)
}
}

class ActionMultiSelectModel(app: Application) : AndroidViewModel(app) {
Expand All @@ -102,11 +139,11 @@ class ActionMultiSelectBottomSheetDialog : BottomSheetDialogFragment() {
}

enum class SelectDialogAction {
ADD_FAVORITES, OFFLINE, DUPLICATE
ADD_FAVORITES, OFFLINE, DUPLICATE, COLOR_FOLDER
}

companion object {
const val DISABLE_SELECT_MODE = "disable_select_mode"
const val SELECT_DIALOG_ACTION = "select_dialog_action"
}
}
}
Loading

0 comments on commit 61868d7

Please sign in to comment.