Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid view mode #3493

Merged
merged 4 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,5 @@ val viewModelModule = module {
viewModel { PreviewImageViewModel(get(), get(), get()) }
viewModel { FileDetailsViewModel(get(), get(), get(), get(), get()) }
viewModel { FileOperationViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { MainFileListViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { MainFileListViewModel(get(), get(), get(), get(), get(), get(), get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,36 @@
package com.owncloud.android.presentation.adapters.filelist

import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.owncloud.android.R
import com.owncloud.android.databinding.GridItemBinding
import com.owncloud.android.databinding.ItemFileListBinding
import com.owncloud.android.databinding.ListFooterBinding
import com.owncloud.android.db.PreferenceManager
import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.files.model.OCFooterFile
import com.owncloud.android.extensions.setPicture
import com.owncloud.android.presentation.diffutils.FileListDiffCallback
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.MimetypeIconUtil
import com.owncloud.android.utils.PreferenceUtils

class FileListAdapter(
private val context: Context,
private val isShowingJustFolders: Boolean,
private val layoutManager: GridLayoutManager,
private val listener: FileListAdapterListener,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {


private var files = mutableListOf<Any>()
private lateinit var viewHolder: RecyclerView.ViewHolder

private val TYPE_ITEMS = 0
private val TYPE_FOOTER = 1

fun updateFileList(filesToAdd: List<OCFile>) {
val diffUtilCallback = FileListDiffCallback(oldList = files, newList = filesToAdd)
Expand All @@ -68,93 +66,183 @@ class FileListAdapter(
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
TYPE_ITEMS -> {
return when (viewType) {
ViewType.LIST_ITEM.ordinal -> {
val binding = ItemFileListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
viewHolder = ViewHolder(binding)
binding.root.apply {
tag = ViewType.LIST_ITEM
filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)
}
ListViewHolder(binding)
}
ViewType.GRID_IMAGE.ordinal -> {
val binding = GridItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
binding.root.tag = ViewType.GRID_IMAGE
GridImageViewHolder(binding)
}
TYPE_FOOTER -> {
ViewType.GRID_ITEM.ordinal -> {
val binding = GridItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
binding.root.tag = ViewType.GRID_ITEM
GridViewHolder(binding)
}
else -> {
val binding = ListFooterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
viewHolder = FooterViewHolder(binding)
binding.root.tag = ViewType.FOOTER
FooterViewHolder(binding)
}
}
return viewHolder
}

override fun getItemCount(): Int = files.size

override fun getItemId(position: Int): Long = position.toLong()

private fun isFooter(position: Int) = position == files.size.minus(1)

override fun getItemViewType(position: Int): Int {
return if (position == files.size.minus(1)) {
TYPE_FOOTER

return if (isFooter(position)) {
ViewType.FOOTER.ordinal
} else {
TYPE_ITEMS
when {
layoutManager.spanCount == 1 -> {
ViewType.LIST_ITEM.ordinal
}
(files[position] as OCFile).isImage -> {
ViewType.GRID_IMAGE.ordinal
}
else -> {
ViewType.GRID_ITEM.ordinal
}
}
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder.itemViewType) {
TYPE_ITEMS -> {
with(holder as ViewHolder) {
with(files[position] as OCFile) {
binding.Filename.text = this.fileName
binding.fileListSize.text = DisplayUtils.bytesToHumanReadable(this.length, context)
binding.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, this.modificationTimestamp)
binding.localFileIndicator.isVisible = false //TODO Modify in the future, when we start the synchronization task.
binding.customCheckbox.isVisible = false //TODO Modify in the future, when we start the multi selection task.
binding.thumbnail.let {
it.tag = this.id
getThumbnailPicture(imageView = it, file = this)

val viewType = getItemViewType(position)


if (!isFooter(position)) { // Is Item

val file = files[position] as OCFile
val name = file.fileName
val fileIcon = holder.itemView.findViewById<ImageView>(R.id.thumbnail).apply {
tag = file.id
}

holder.itemView.findViewById<LinearLayout>(R.id.ListItemLayout)?.apply {
contentDescription = "LinearLayout-$name"

// Allow or disallow touches with other visible windows
filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)
}

when (viewType) {
ViewType.LIST_ITEM.ordinal -> {
val view = holder as ListViewHolder
view.binding.let {
it.fileListConstraintLayout.apply {
filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)
}
//TODO Check this with FileListListAdapter.java and its viewType (LIST or GRID)
getSharedIcon(imageView = binding.sharedIcon, file = this)
binding.root.setOnClickListener {
listener.clickItem(this)

it.Filename.text = file.fileName
it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context)
it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)

}
}
ViewType.GRID_ITEM.ordinal -> {
//Filename
val view = holder as GridViewHolder
view.binding.Filename.text = file.fileName
}

ViewType.GRID_IMAGE.ordinal -> {
//SharedIcon
val view = holder as GridImageViewHolder
view.binding.let {
if (file.sharedByLink) {
it.sharedIcon.apply {
setImageResource(R.drawable.ic_shared_by_link)
visibility = View.VISIBLE
bringToFront()
}
} else if (file.sharedWithSharee == true || file.isSharedWithMe) {
it.sharedIcon.apply {
setImageResource(R.drawable.shared_via_users)
visibility = View.VISIBLE
bringToFront()
}
} else {
it.sharedIcon.visibility = View.GONE
}
}
}

}

//TODO Delete it when manage state sync.
holder.itemView.findViewById<ImageView>(R.id.localFileIndicator).apply {
visibility = View.GONE
}
TYPE_FOOTER -> {
if (!isShowingJustFolders) {
with(holder as FooterViewHolder) {
with(files[position] as OCFooterFile) {
binding.footerText.text = this.text
holder.itemView.findViewById<ImageView>(R.id.sharedIcon).apply {
visibility = View.GONE
}


holder.itemView.setOnClickListener { listener.clickItem(file) }

val checkBoxV = holder.itemView.findViewById<ImageView>(R.id.custom_checkbox).apply {
visibility = View.GONE
}
holder.itemView.setBackgroundColor(Color.WHITE)

if (file.isFolder) {
//Folder
fileIcon.setImageResource(
MimetypeIconUtil.getFolderTypeIconId(
file.isSharedWithMe || file.sharedWithSharee == true,
file.sharedByLink
)
)
} else {
// Set file icon depending on its mimetype. Ask for thumbnail later.
fileIcon.setImageResource(MimetypeIconUtil.getFileTypeIconId(file.mimeType, file.fileName))
if (file.remoteId != null) {
val thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId)
if (thumbnail != null) {
fileIcon.setImageBitmap(thumbnail)
}
if (file.needsToUpdateThumbnail) {
// generate new Thumbnail
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
/*val task = ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, storageManager, account)
val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(context.resources, thumbnail, task)
jabarros marked this conversation as resolved.
Show resolved Hide resolved

// If drawable is not visible, do not update it.
if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
fileIcon.setImageDrawable(asyncDrawable)
}
task.execute(file)*/
}
}

if (file.mimeType == "image/png") {
fileIcon.setBackgroundColor(ContextCompat.getColor(context, R.color.background_color))
}
}
}
}
}

private fun getThumbnailPicture(imageView: ImageView, file: OCFile) {
if (file.isFolder) {
imageView.setPicture(
MimetypeIconUtil.getFolderTypeIconId(file.isSharedWithMe || file.sharedWithSharee ?: false, file.sharedByLink)
)
} else {
// Set file icon depending on its mimetype.
imageView.setPicture(MimetypeIconUtil.getFileTypeIconId(file.mimeType, file.fileName))
if (file.mimeType.contentEquals("image/png")) {
imageView.setBackgroundColor(ContextCompat.getColor(context, R.color.background_color))
} else { //Is Footer
if (viewType == ViewType.FOOTER.ordinal && !isShowingJustFolders) {
val view = holder as FooterViewHolder
val file = files[position] as OCFooterFile
view.binding.footerText.text = file.text
}
}
}

private fun getSharedIcon(imageView: ImageView, file: OCFile) {
if (file.sharedByLink) {
imageView.setImageResource(R.drawable.ic_shared_by_link)
imageView.visibility = View.VISIBLE
imageView.bringToFront()
} else if (file.sharedWithSharee == true || file.isSharedWithMe) {
imageView.setImageResource(R.drawable.shared_via_users)
imageView.visibility = View.VISIBLE
imageView.bringToFront()
} else {
imageView.visibility = View.GONE
}
}

private fun manageListOfFilesAndGenerateText(list: List<OCFile>): String {
var filesCount = 0
var foldersCount = 0
Expand Down Expand Up @@ -224,6 +312,12 @@ class FileListAdapter(
fun clickItem(ocFile: OCFile)
}

inner class ViewHolder(val binding: ItemFileListBinding) : RecyclerView.ViewHolder(binding.root)
inner class GridViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
inner class GridImageViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
inner class ListViewHolder(val binding: ItemFileListBinding) : RecyclerView.ViewHolder(binding.root)
inner class FooterViewHolder(val binding: ListFooterBinding) : RecyclerView.ViewHolder(binding.root)

enum class ViewType {
LIST_ITEM, GRID_IMAGE, GRID_ITEM, FOOTER
}
}
Loading