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

Simple list have been created. #3451

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 @@ -23,6 +23,7 @@
package com.owncloud.android.dependecyinjection

import com.owncloud.android.MainApp
import com.owncloud.android.presentation.ui.files.filelist.MainFileListViewModel
import com.owncloud.android.presentation.ui.files.operations.FileOperationViewModel
import com.owncloud.android.presentation.viewmodels.authentication.OCAuthenticationViewModel
import com.owncloud.android.presentation.viewmodels.capabilities.OCCapabilityViewModel
Expand Down Expand Up @@ -74,4 +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()) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* ownCloud Android client application
*
* @author Fernando Sanz Velasco
* Copyright (C) 2021 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package com.owncloud.android.extensions

import android.annotation.SuppressLint
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy

@SuppressLint("CheckResult")
fun ImageView.setPicture(imageToLoad: Int) {
Glide.with(this)
.load(imageToLoad)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(this)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* ownCloud Android client application
*
* @author Fernando Sanz Velasco
* Copyright (C) 2021 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package com.owncloud.android.presentation.adapters.filelist

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.owncloud.android.R
import com.owncloud.android.databinding.ItemFileListBinding
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.extensions.setPicture
import com.owncloud.android.presentation.diffutils.FileListDiffCallback
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.MimetypeIconUtil

class FileListAdapter(
private val context: Context
) : RecyclerView.Adapter<FileListAdapter.ViewHolder>() {

private val files = mutableListOf<OCFile>()

fun updateFileList(filesToAdd: List<OCFile>) {
val diffUtilCallback = FileListDiffCallback(oldList = files, newList = filesToAdd)
val diffResult = DiffUtil.calculateDiff(diffUtilCallback)
files.clear()
files.addAll(filesToAdd)
diffResult.dispatchUpdatesTo(this)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemFileListBinding.inflate(LayoutInflater.from(parent.context), parent, false)

return ViewHolder(binding)
}

override fun getItemCount(): Int = files.size

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

override fun getItemViewType(position: Int): Int = position

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
with(holder) {
with(files[position]) {
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)
}
//TODO Check this with FileListListAdapter.java and its viewType (LIST or GRID)
getSharedIcon(imageView = binding.sharedIcon, file = this)
}
}
}

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))
}
}
}

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
}
}

inner class ViewHolder(val binding: ItemFileListBinding) : RecyclerView.ViewHolder(binding.root)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* ownCloud Android client application
*
* @author Fernando Sanz Velasco
* Copyright (C) 2021 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package com.owncloud.android.presentation.diffutils

import androidx.recyclerview.widget.DiffUtil
import com.owncloud.android.domain.files.model.OCFile

class FileListDiffCallback(private val oldList: List<OCFile>, private val newList: List<OCFile>) : DiffUtil.Callback() {

override fun getOldListSize(): Int = oldList.size

override fun getNewListSize(): Int = newList.size

override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id === newList[newItemPosition].id
}

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val (_, value, name) = oldList[oldItemPosition]
val (_, value1, name1) = newList[newItemPosition]
return name == name1 && value == value1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,72 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.owncloud.android.databinding.MainFileListFragmentBinding
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.utils.Event
import com.owncloud.android.presentation.UIResult
import com.owncloud.android.presentation.adapters.filelist.FileListAdapter
import org.koin.androidx.viewmodel.ext.android.viewModel

class MainFileListFragment : Fragment() {

private val viewModel by viewModels<MainFileListViewModel>()
private val mainFileListViewModel by viewModel<MainFileListViewModel>()

private var _binding: MainFileListFragmentBinding? = null
private val binding get() = _binding!!

private lateinit var fileListAdapter: FileListAdapter

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = MainFileListFragmentBinding.inflate(inflater, container, false)

return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
subscribeToViewModels()
}

private fun initViews() {
//Set RecyclerView and its adapter.
fileListAdapter = FileListAdapter(context = requireContext())
binding.recyclerViewMainFileList.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = fileListAdapter

}
}

private fun subscribeToViewModels() {
//Observe the action of retrieving the list of files.
mainFileListViewModel.getFilesListStatusLiveData.observe(viewLifecycleOwner, Event.EventObserver { result ->
when (result) {
is UIResult.Error -> {} //TODO Manage Error
is UIResult.Loading -> {} //TODO Manage Loading
is UIResult.Success -> fileListAdapter.updateFileList(filesToAdd = result.data ?: emptyList())
}
})
}

fun listDirectory(directory: OCFile) {
mainFileListViewModel.listDirectory(directory = directory)
}

override fun onDestroy() {
super.onDestroy()
_binding = null
}

companion object {
fun newInstance(): MainFileListFragment {
val args = Bundle()
return MainFileListFragment().apply { arguments = args }
}
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,60 @@
/**
* ownCloud Android client application
*
* @author Fernando Sanz Velasco
* Copyright (C) 2021 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package com.owncloud.android.presentation.ui.files.filelist

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.owncloud.android.domain.UseCaseResult
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.files.usecases.GetFolderContentUseCase
import com.owncloud.android.domain.utils.Event
import com.owncloud.android.presentation.UIResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class MainFileListViewModel(
private val getFolderContentUseCase: GetFolderContentUseCase
) : ViewModel() {

private var file: OCFile? = null

private val _getFilesListStatusLiveData = MutableLiveData<Event<UIResult<List<OCFile>>>>()
val getFilesListStatusLiveData: LiveData<Event<UIResult<List<OCFile>>>>
get() = _getFilesListStatusLiveData

private fun getFilesList(folderId: Long) {
viewModelScope.launch(Dispatchers.IO) {
_getFilesListStatusLiveData.postValue(Event(UIResult.Loading()))
getFolderContentUseCase.execute(GetFolderContentUseCase.Params(folderId = folderId)).let {
when (it) {
is UseCaseResult.Error -> _getFilesListStatusLiveData.postValue(Event(UIResult.Error(it.getThrowableOrNull())))
is UseCaseResult.Success -> _getFilesListStatusLiveData.postValue(Event(UIResult.Success(it.getDataOrNull())))
}
}
}
}

class MainFileListViewModel : ViewModel() {
// TODO: Implement the ViewModel
}
fun listDirectory(directory: OCFile) {
getFilesList(directory.id!!)
}
}
21 changes: 13 additions & 8 deletions owncloudApp/src/main/res/layout/main_file_list_fragment.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
~ ownCloud Android client application
~
~ @author Fernando Sanz Velasco
Expand All @@ -19,15 +18,21 @@
~
-->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.ui.files.filelist.MainFileListFragment">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_main_file_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/item_file_list" />

</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>