diff --git a/app/src/main/java/org/linphone/ui/main/chat/adapter/ConversationsFilesAdapter.kt b/app/src/main/java/org/linphone/ui/main/chat/adapter/ConversationsFilesAdapter.kt new file mode 100644 index 000000000..af00ad335 --- /dev/null +++ b/app/src/main/java/org/linphone/ui/main/chat/adapter/ConversationsFilesAdapter.kt @@ -0,0 +1,106 @@ +package org.linphone.ui.main.chat.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.annotation.UiThread +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import org.linphone.R +import org.linphone.databinding.ChatDocumentContentListCellBinding +import org.linphone.databinding.ChatMediaContentGridCellBinding +import org.linphone.ui.main.chat.model.FileModel + +class ConversationsFilesAdapter : ListAdapter( + FilesDiffCallback() +) { + companion object { + const val MEDIA_FILE = 1 + const val DOCUMENT_FILE = 2 + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + MEDIA_FILE -> createMediaFileViewHolder(parent) + else -> createDocumentFileViewHolder(parent) + } + } + + override fun getItemViewType(position: Int): Int { + val data = getItem(position) + if (data.isMedia) return MEDIA_FILE + return DOCUMENT_FILE + } + + private fun createMediaFileViewHolder(parent: ViewGroup): RecyclerView.ViewHolder { + val binding: ChatMediaContentGridCellBinding = DataBindingUtil.inflate( + LayoutInflater.from(parent.context), + R.layout.chat_media_content_grid_cell, + parent, + false + ) + val viewHolder = MediaFileViewHolder(binding) + binding.apply { + lifecycleOwner = parent.findViewTreeLifecycleOwner() + } + return viewHolder + } + + private fun createDocumentFileViewHolder(parent: ViewGroup): RecyclerView.ViewHolder { + val binding: ChatDocumentContentListCellBinding = DataBindingUtil.inflate( + LayoutInflater.from(parent.context), + R.layout.chat_document_content_list_cell, + parent, + false + ) + val viewHolder = DocumentFileViewHolder(binding) + binding.apply { + lifecycleOwner = parent.findViewTreeLifecycleOwner() + } + return viewHolder + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val fileModel = getItem(position) + when (holder) { + is MediaFileViewHolder -> holder.bind(fileModel) + is DocumentFileViewHolder -> holder.bind(fileModel) + } + } + + inner class MediaFileViewHolder( + val binding: ChatMediaContentGridCellBinding + ) : RecyclerView.ViewHolder(binding.root) { + @UiThread + fun bind(fileModel: FileModel) { + with(binding) { + model = fileModel + executePendingBindings() + } + } + } + + inner class DocumentFileViewHolder( + val binding: ChatDocumentContentListCellBinding + ) : RecyclerView.ViewHolder(binding.root) { + @UiThread + fun bind(fileModel: FileModel) { + with(binding) { + model = fileModel + executePendingBindings() + } + } + } + + private class FilesDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: FileModel, newItem: FileModel): Boolean { + return oldItem.file == newItem.file && oldItem.fileName == newItem.fileName + } + + override fun areContentsTheSame(oldItem: FileModel, newItem: FileModel): Boolean { + return true + } + } +} diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationDocumentsListFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationDocumentsListFragment.kt index be2cc0d81..adc628486 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationDocumentsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationDocumentsListFragment.kt @@ -31,10 +31,12 @@ import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs +import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.ChatDocumentsFragmentBinding import org.linphone.ui.main.MainActivity +import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter import org.linphone.ui.main.chat.viewmodel.ConversationDocumentsListViewModel import org.linphone.ui.main.fragment.SlidingPaneChildFragment import org.linphone.utils.Event @@ -50,12 +52,20 @@ class ConversationDocumentsListFragment : SlidingPaneChildFragment() { private lateinit var viewModel: ConversationDocumentsListViewModel + private lateinit var adapter: ConversationsFilesAdapter + private val args: ConversationMediaListFragmentArgs by navArgs() override fun goBack(): Boolean { return findNavController().popBackStack() } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + adapter = ConversationsFilesAdapter() + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -82,6 +92,14 @@ class ConversationDocumentsListFragment : SlidingPaneChildFragment() { val chatRoom = sharedViewModel.displayedChatRoom viewModel.findChatRoom(chatRoom, localSipUri, remoteSipUri) + binding.documentsList.setHasFixedSize(true) + val layoutManager = LinearLayoutManager(requireContext()) + binding.documentsList.layoutManager = layoutManager + + if (binding.documentsList.adapter != adapter) { + binding.documentsList.adapter = adapter + } + binding.setBackClickListener { goBack() } @@ -95,12 +113,12 @@ class ConversationDocumentsListFragment : SlidingPaneChildFragment() { } } - viewModel.documentsList.observe(viewLifecycleOwner) { - val count = it.size + viewModel.documentsList.observe(viewLifecycleOwner) { items -> + val count = items.size Log.i( "$TAG Found [$count] documents for conversation with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" ) - // TODO: FIXME: use Adapter + adapter.submitList(items) } viewModel.openDocumentEvent.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationMediaListFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationMediaListFragment.kt index c1f370bab..e6e59e284 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationMediaListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationMediaListFragment.kt @@ -31,10 +31,13 @@ import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.ChatMediaFragmentBinding import org.linphone.ui.main.MainActivity +import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter import org.linphone.ui.main.chat.viewmodel.ConversationMediaListViewModel import org.linphone.ui.main.fragment.SlidingPaneChildFragment import org.linphone.utils.Event @@ -50,12 +53,20 @@ class ConversationMediaListFragment : SlidingPaneChildFragment() { private lateinit var viewModel: ConversationMediaListViewModel + private lateinit var adapter: ConversationsFilesAdapter + private val args: ConversationMediaListFragmentArgs by navArgs() override fun goBack(): Boolean { return findNavController().popBackStack() } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + adapter = ConversationsFilesAdapter() + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -82,6 +93,19 @@ class ConversationMediaListFragment : SlidingPaneChildFragment() { val chatRoom = sharedViewModel.displayedChatRoom viewModel.findChatRoom(chatRoom, localSipUri, remoteSipUri) + binding.mediaList.setHasFixedSize(true) + val layoutManager = object : GridLayoutManager(requireContext(), 4) { + override fun checkLayoutParams(lp: RecyclerView.LayoutParams): Boolean { + lp.width = width / spanCount + return true + } + } + binding.mediaList.layoutManager = layoutManager + + if (binding.mediaList.adapter != adapter) { + binding.mediaList.adapter = adapter + } + binding.setBackClickListener { goBack() } @@ -95,12 +119,12 @@ class ConversationMediaListFragment : SlidingPaneChildFragment() { } } - viewModel.mediaList.observe(viewLifecycleOwner) { - val count = it.size + viewModel.mediaList.observe(viewLifecycleOwner) { items -> + val count = items.size Log.i( "$TAG Found [$count] media for conversation with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" ) - // TODO: FIXME: use Adapter + adapter.submitList(items) } viewModel.openMediaEvent.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationDocumentsListViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationDocumentsListViewModel.kt index 81e7dd41e..56d1c929f 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationDocumentsListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationDocumentsListViewModel.kt @@ -128,8 +128,8 @@ class ConversationDocumentsListViewModel @UiThread constructor() : ViewModel() { } Log.i("$TAG [${documents.size}] documents have been processed") } - documentsList.postValue(list) + documentsList.postValue(list) operationInProgress.postValue(false) } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationMediaListViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationMediaListViewModel.kt index 6cbbc91ee..5cae2cb26 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationMediaListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationMediaListViewModel.kt @@ -132,8 +132,8 @@ class ConversationMediaListViewModel @UiThread constructor() : ViewModel() { } Log.i("$TAG [${media.size}] media have been processed") } - mediaList.postValue(list) + mediaList.postValue(list) operationInProgress.postValue(false) } } diff --git a/app/src/main/res/layout/chat_documents_fragment.xml b/app/src/main/res/layout/chat_documents_fragment.xml index 7c3a375a0..a4a3a37eb 100644 --- a/app/src/main/res/layout/chat_documents_fragment.xml +++ b/app/src/main/res/layout/chat_documents_fragment.xml @@ -48,26 +48,15 @@ app:layout_constraintStart_toEndOf="@id/back" app:layout_constraintTop_toTopOf="parent"/> - - - - - + app:layout_constraintTop_toBottomOf="@id/title" /> + android:layout_height="wrap_content"> - - - - - + app:layout_constraintTop_toBottomOf="@id/title" />