mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Load contents by chunks instead of loading all of them at once
This commit is contained in:
parent
31e15ddfca
commit
ae7a3c5bce
7 changed files with 200 additions and 41 deletions
|
|
@ -33,6 +33,7 @@ Group changes to describe their impact on the project, as follows:
|
||||||
### Changed
|
### Changed
|
||||||
- Hide SIP address/phone number picker dialog if contact has exactly one SIP address matching both the app default domain & the currently selected account domain
|
- Hide SIP address/phone number picker dialog if contact has exactly one SIP address matching both the app default domain & the currently selected account domain
|
||||||
- Improved UI on tablets with screen sw600dp and higher, will look more like our desktop app
|
- Improved UI on tablets with screen sw600dp and higher, will look more like our desktop app
|
||||||
|
- Now loading media/documents contents in conversation by chunks (instead of all of them at once)
|
||||||
- Simplified audio device name in settings
|
- Simplified audio device name in settings
|
||||||
- Reworked some settings (moved calls related ones from advanced settings to advanced calls settings)
|
- Reworked some settings (moved calls related ones from advanced settings to advanced calls settings)
|
||||||
- Increased shared media preview size in chat
|
- Increased shared media preview size in chat
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
* Copyright (c) 2010-2025 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-android
|
* This file is part of linphone-android
|
||||||
* (see https://www.linphone.org).
|
* (see https://www.linphone.org).
|
||||||
|
|
@ -21,13 +21,12 @@ package org.linphone.ui.main.chat
|
||||||
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
internal abstract class ConversationScrollListener(private val mLayoutManager: LinearLayoutManager) :
|
internal abstract class RecyclerViewScrollListener(private val layoutManager: LinearLayoutManager, private val visibleThreshold: Int, private val scrollingTopToBottom: Boolean) :
|
||||||
RecyclerView.OnScrollListener() {
|
RecyclerView.OnScrollListener() {
|
||||||
companion object {
|
companion object {
|
||||||
// The minimum amount of items to have below your current scroll position
|
private const val TAG = "[RecyclerView Scroll Listener]"
|
||||||
// before loading more.
|
|
||||||
private const val VISIBLE_THRESHOLD = 5
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The total number of items in the data set after the last load
|
// The total number of items in the data set after the last load
|
||||||
|
|
@ -40,9 +39,9 @@ internal abstract class ConversationScrollListener(private val mLayoutManager: L
|
||||||
// We are given a few useful parameters to help us work out if we need to load some more data,
|
// We are given a few useful parameters to help us work out if we need to load some more data,
|
||||||
// but first we check if we are waiting for the previous load to finish.
|
// but first we check if we are waiting for the previous load to finish.
|
||||||
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
|
||||||
val totalItemCount = mLayoutManager.itemCount
|
val totalItemCount = layoutManager.itemCount
|
||||||
val firstVisibleItemPosition: Int = mLayoutManager.findFirstVisibleItemPosition()
|
val firstVisibleItemPosition: Int = layoutManager.findFirstVisibleItemPosition()
|
||||||
val lastVisibleItemPosition: Int = mLayoutManager.findLastVisibleItemPosition()
|
val lastVisibleItemPosition: Int = layoutManager.findLastVisibleItemPosition()
|
||||||
|
|
||||||
// If the total item count is zero and the previous isn't, assume the
|
// If the total item count is zero and the previous isn't, assume the
|
||||||
// list is invalidated and should be reset back to initial state
|
// list is invalidated and should be reset back to initial state
|
||||||
|
|
@ -64,21 +63,34 @@ internal abstract class ConversationScrollListener(private val mLayoutManager: L
|
||||||
val userHasScrolledUp = lastVisibleItemPosition != totalItemCount - 1
|
val userHasScrolledUp = lastVisibleItemPosition != totalItemCount - 1
|
||||||
if (userHasScrolledUp) {
|
if (userHasScrolledUp) {
|
||||||
onScrolledUp()
|
onScrolledUp()
|
||||||
|
Log.d("$TAG Scrolled up")
|
||||||
} else {
|
} else {
|
||||||
onScrolledToEnd()
|
onScrolledToEnd()
|
||||||
|
Log.d("$TAG Scrolled to end")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it isn’t currently loading, we check to see if we have breached
|
// If it isn’t currently loading, we check to see if we have breached
|
||||||
// the mVisibleThreshold and need to reload more data.
|
// the visibleThreshold and need to reload more data.
|
||||||
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
|
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
|
||||||
// threshold should reflect how many total columns there are too
|
// threshold should reflect how many total columns there are too
|
||||||
if (!loading &&
|
if (!loading) {
|
||||||
firstVisibleItemPosition < VISIBLE_THRESHOLD &&
|
if (scrollingTopToBottom) {
|
||||||
firstVisibleItemPosition >= 0 &&
|
if (lastVisibleItemPosition >= totalItemCount - visibleThreshold) {
|
||||||
lastVisibleItemPosition < totalItemCount - VISIBLE_THRESHOLD
|
Log.d(
|
||||||
) {
|
"$TAG Last visible item position [$lastVisibleItemPosition] reached [${totalItemCount - visibleThreshold}], loading more (current total items is [$totalItemCount])"
|
||||||
onLoadMore(totalItemCount)
|
)
|
||||||
loading = true
|
loading = true
|
||||||
|
onLoadMore(totalItemCount)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (firstVisibleItemPosition < visibleThreshold) {
|
||||||
|
Log.d(
|
||||||
|
"$TAG First visible item position [$firstVisibleItemPosition] < visibleThreshold [$visibleThreshold], loading more (current total items is [$totalItemCount])"
|
||||||
|
)
|
||||||
|
loading = true
|
||||||
|
onLoadMore(totalItemCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +33,7 @@ import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.ChatDocumentsFragmentBinding
|
import org.linphone.databinding.ChatDocumentsFragmentBinding
|
||||||
|
import org.linphone.ui.main.chat.RecyclerViewScrollListener
|
||||||
import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter
|
import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter
|
||||||
import org.linphone.ui.main.chat.model.FileModel
|
import org.linphone.ui.main.chat.model.FileModel
|
||||||
import org.linphone.ui.main.chat.viewmodel.ConversationDocumentsListViewModel
|
import org.linphone.ui.main.chat.viewmodel.ConversationDocumentsListViewModel
|
||||||
|
|
@ -57,6 +58,8 @@ class ConversationDocumentsListFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
private val args: ConversationMediaListFragmentArgs by navArgs()
|
private val args: ConversationMediaListFragmentArgs by navArgs()
|
||||||
|
|
||||||
|
private lateinit var scrollListener: RecyclerViewScrollListener
|
||||||
|
|
||||||
override fun goBack(): Boolean {
|
override fun goBack(): Boolean {
|
||||||
try {
|
try {
|
||||||
return findNavController().popBackStack()
|
return findNavController().popBackStack()
|
||||||
|
|
@ -130,6 +133,40 @@ class ConversationDocumentsListFragment : SlidingPaneChildFragment() {
|
||||||
goToFileViewer(model)
|
goToFileViewer(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollListener = object : RecyclerViewScrollListener(layoutManager, 4, true) {
|
||||||
|
@UiThread
|
||||||
|
override fun onLoadMore(totalItemsCount: Int) {
|
||||||
|
Log.i("$TAG Asking for more data to display, currently displayed items count is [$totalItemsCount]")
|
||||||
|
viewModel.loadMoreData(totalItemsCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
override fun onScrolledUp() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
override fun onScrolledToEnd() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
if (::scrollListener.isInitialized) {
|
||||||
|
binding.documentsList.addOnScrollListener(scrollListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
|
||||||
|
if (::scrollListener.isInitialized) {
|
||||||
|
binding.documentsList.removeOnScrollListener(scrollListener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun goToFileViewer(fileModel: FileModel) {
|
private fun goToFileViewer(fileModel: FileModel) {
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.ChatConversationFragmentBinding
|
import org.linphone.databinding.ChatConversationFragmentBinding
|
||||||
import org.linphone.databinding.ChatConversationPopupMenuBinding
|
import org.linphone.databinding.ChatConversationPopupMenuBinding
|
||||||
import org.linphone.ui.GenericActivity
|
import org.linphone.ui.GenericActivity
|
||||||
import org.linphone.ui.main.chat.ConversationScrollListener
|
import org.linphone.ui.main.chat.RecyclerViewScrollListener
|
||||||
import org.linphone.ui.main.chat.adapter.ConversationEventAdapter
|
import org.linphone.ui.main.chat.adapter.ConversationEventAdapter
|
||||||
import org.linphone.ui.main.chat.adapter.MessageBottomSheetAdapter
|
import org.linphone.ui.main.chat.adapter.MessageBottomSheetAdapter
|
||||||
import org.linphone.ui.main.chat.model.FileModel
|
import org.linphone.ui.main.chat.model.FileModel
|
||||||
|
|
@ -298,7 +298,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var scrollListener: ConversationScrollListener
|
private lateinit var scrollListener: RecyclerViewScrollListener
|
||||||
|
|
||||||
private lateinit var headerItemDecoration: RecyclerViewHeaderDecoration
|
private lateinit var headerItemDecoration: RecyclerViewHeaderDecoration
|
||||||
|
|
||||||
|
|
@ -1005,7 +1005,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
binding.sendArea.messageToSend.addTextChangedListener(textObserver)
|
binding.sendArea.messageToSend.addTextChangedListener(textObserver)
|
||||||
|
|
||||||
scrollListener = object : ConversationScrollListener(layoutManager) {
|
scrollListener = object : RecyclerViewScrollListener(layoutManager, 5, false) {
|
||||||
@UiThread
|
@UiThread
|
||||||
override fun onLoadMore(totalItemsCount: Int) {
|
override fun onLoadMore(totalItemsCount: Int) {
|
||||||
if (viewModel.searchInProgress.value == false) {
|
if (viewModel.searchInProgress.value == false) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import org.linphone.R
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.ChatMediaFragmentBinding
|
import org.linphone.databinding.ChatMediaFragmentBinding
|
||||||
import org.linphone.ui.GenericActivity
|
import org.linphone.ui.GenericActivity
|
||||||
|
import org.linphone.ui.main.chat.RecyclerViewScrollListener
|
||||||
import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter
|
import org.linphone.ui.main.chat.adapter.ConversationsFilesAdapter
|
||||||
import org.linphone.ui.main.chat.model.FileModel
|
import org.linphone.ui.main.chat.model.FileModel
|
||||||
import org.linphone.ui.main.chat.viewmodel.ConversationMediaListViewModel
|
import org.linphone.ui.main.chat.viewmodel.ConversationMediaListViewModel
|
||||||
|
|
@ -58,6 +59,8 @@ class ConversationMediaListFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
private val args: ConversationMediaListFragmentArgs by navArgs()
|
private val args: ConversationMediaListFragmentArgs by navArgs()
|
||||||
|
|
||||||
|
private lateinit var scrollListener: RecyclerViewScrollListener
|
||||||
|
|
||||||
override fun goBack(): Boolean {
|
override fun goBack(): Boolean {
|
||||||
try {
|
try {
|
||||||
return findNavController().popBackStack()
|
return findNavController().popBackStack()
|
||||||
|
|
@ -159,6 +162,40 @@ class ConversationMediaListFragment : SlidingPaneChildFragment() {
|
||||||
goToFileViewer(model)
|
goToFileViewer(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollListener = object : RecyclerViewScrollListener(layoutManager, spanCount, true) {
|
||||||
|
@UiThread
|
||||||
|
override fun onLoadMore(totalItemsCount: Int) {
|
||||||
|
Log.i("$TAG Asking for more data to display, currently displayed items count is [$totalItemsCount]")
|
||||||
|
viewModel.loadMoreData(totalItemsCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
override fun onScrolledUp() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
override fun onScrolledToEnd() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
if (::scrollListener.isInitialized) {
|
||||||
|
binding.mediaList.addOnScrollListener(scrollListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
|
||||||
|
if (::scrollListener.isInitialized) {
|
||||||
|
binding.mediaList.removeOnScrollListener(scrollListener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun goToFileViewer(fileModel: FileModel) {
|
private fun goToFileViewer(fileModel: FileModel) {
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,21 @@ package org.linphone.ui.main.chat.viewmodel
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.Content
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.chat.model.FileModel
|
import org.linphone.ui.main.chat.model.FileModel
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class ConversationDocumentsListViewModel
|
class ConversationDocumentsListViewModel
|
||||||
@UiThread
|
@UiThread
|
||||||
constructor() : AbstractConversationViewModel() {
|
constructor() : AbstractConversationViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "[Conversation Documents List ViewModel]"
|
private const val TAG = "[Conversation Documents List ViewModel]"
|
||||||
|
|
||||||
|
private const val CONTENTS_PER_PAGE = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
val documentsList = MutableLiveData<List<FileModel>>()
|
val documentsList = MutableLiveData<List<FileModel>>()
|
||||||
|
|
@ -42,6 +47,8 @@ class ConversationDocumentsListViewModel
|
||||||
MutableLiveData<Event<FileModel>>()
|
MutableLiveData<Event<FileModel>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var totalDocumentsCount: Int = -1
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun afterNotifyingChatRoomFound(sameOne: Boolean) {
|
override fun afterNotifyingChatRoomFound(sameOne: Boolean) {
|
||||||
loadDocumentsList()
|
loadDocumentsList()
|
||||||
|
|
@ -56,16 +63,48 @@ class ConversationDocumentsListViewModel
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private fun loadDocumentsList() {
|
private fun loadDocumentsList() {
|
||||||
operationInProgress.postValue(true)
|
operationInProgress.postValue(true)
|
||||||
|
|
||||||
val list = arrayListOf<FileModel>()
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Loading document contents for conversation [${LinphoneUtils.getConversationId(
|
"$TAG Loading document contents for conversation [${LinphoneUtils.getConversationId(
|
||||||
chatRoom
|
chatRoom
|
||||||
)}]"
|
)}]"
|
||||||
)
|
)
|
||||||
val documents = chatRoom.documentContents
|
|
||||||
Log.i("$TAG [${documents.size}] documents have been fetched")
|
totalDocumentsCount = chatRoom.documentContentsSize
|
||||||
for (documentContent in documents) {
|
Log.i("$TAG Document contents size is [$totalDocumentsCount]")
|
||||||
|
|
||||||
|
val contentsToLoad = min(totalDocumentsCount, CONTENTS_PER_PAGE)
|
||||||
|
val contents = chatRoom.getDocumentContentsRange(0, contentsToLoad)
|
||||||
|
Log.i("$TAG [${contents.size}] documents have been fetched")
|
||||||
|
|
||||||
|
documentsList.postValue(getFileModelsListFromContents(contents))
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun loadMoreData(totalItemsCount: Int) {
|
||||||
|
coreContext.postOnCoreThread {
|
||||||
|
Log.i("$TAG Loading more data, current total is $totalItemsCount, max size is $totalDocumentsCount")
|
||||||
|
|
||||||
|
if (totalItemsCount < totalDocumentsCount) {
|
||||||
|
var upperBound: Int = totalItemsCount + CONTENTS_PER_PAGE
|
||||||
|
if (upperBound > totalDocumentsCount) {
|
||||||
|
upperBound = totalDocumentsCount
|
||||||
|
}
|
||||||
|
val contents = chatRoom.getDocumentContentsRange(totalItemsCount, upperBound)
|
||||||
|
Log.i("$TAG [${contents.size}] contents loaded, adding them to list")
|
||||||
|
|
||||||
|
val list = arrayListOf<FileModel>()
|
||||||
|
list.addAll(documentsList.value.orEmpty())
|
||||||
|
list.addAll(getFileModelsListFromContents(contents))
|
||||||
|
documentsList.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
private fun getFileModelsListFromContents(contents: Array<Content>): ArrayList<FileModel> {
|
||||||
|
val list = arrayListOf<FileModel>()
|
||||||
|
for (documentContent in contents) {
|
||||||
val isEncrypted = documentContent.isFileEncrypted
|
val isEncrypted = documentContent.isFileEncrypted
|
||||||
val originalPath = documentContent.filePath.orEmpty()
|
val originalPath = documentContent.filePath.orEmpty()
|
||||||
val path = if (isEncrypted) {
|
val path = if (isEncrypted) {
|
||||||
|
|
@ -94,14 +133,11 @@ class ConversationDocumentsListViewModel
|
||||||
|
|
||||||
val model =
|
val model =
|
||||||
FileModel(path, name, size, timestamp, isEncrypted, originalPath, ephemeral) {
|
FileModel(path, name, size, timestamp, isEncrypted, originalPath, ephemeral) {
|
||||||
openDocumentEvent.postValue(Event(it))
|
openDocumentEvent.postValue(Event(it))
|
||||||
}
|
}
|
||||||
list.add(model)
|
list.add(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return list
|
||||||
Log.i("$TAG [${documents.size}] documents have been processed")
|
|
||||||
documentsList.postValue(list)
|
|
||||||
operationInProgress.postValue(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,21 @@ package org.linphone.ui.main.chat.viewmodel
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.Content
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.chat.model.FileModel
|
import org.linphone.ui.main.chat.model.FileModel
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class ConversationMediaListViewModel
|
class ConversationMediaListViewModel
|
||||||
@UiThread
|
@UiThread
|
||||||
constructor() : AbstractConversationViewModel() {
|
constructor() : AbstractConversationViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "[Conversation Media List ViewModel]"
|
private const val TAG = "[Conversation Media List ViewModel]"
|
||||||
|
|
||||||
|
private const val CONTENTS_PER_PAGE = 50
|
||||||
}
|
}
|
||||||
|
|
||||||
val mediaList = MutableLiveData<List<FileModel>>()
|
val mediaList = MutableLiveData<List<FileModel>>()
|
||||||
|
|
@ -42,6 +47,8 @@ class ConversationMediaListViewModel
|
||||||
MutableLiveData<Event<FileModel>>()
|
MutableLiveData<Event<FileModel>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var totalMediaCount: Int = -1
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun afterNotifyingChatRoomFound(sameOne: Boolean) {
|
override fun afterNotifyingChatRoomFound(sameOne: Boolean) {
|
||||||
loadMediaList()
|
loadMediaList()
|
||||||
|
|
@ -56,16 +63,48 @@ class ConversationMediaListViewModel
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private fun loadMediaList() {
|
private fun loadMediaList() {
|
||||||
operationInProgress.postValue(true)
|
operationInProgress.postValue(true)
|
||||||
|
|
||||||
val list = arrayListOf<FileModel>()
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Loading media contents for conversation [${LinphoneUtils.getConversationId(
|
"$TAG Loading media contents for conversation [${LinphoneUtils.getConversationId(
|
||||||
chatRoom
|
chatRoom
|
||||||
)}]"
|
)}]"
|
||||||
)
|
)
|
||||||
val media = chatRoom.mediaContents
|
|
||||||
Log.i("$TAG [${media.size}] media have been fetched")
|
totalMediaCount = chatRoom.mediaContentsSize
|
||||||
for (mediaContent in media) {
|
Log.i("$TAG Media contents size is [$totalMediaCount]")
|
||||||
|
|
||||||
|
val contentsToLoad = min(totalMediaCount, CONTENTS_PER_PAGE)
|
||||||
|
val contents = chatRoom.getMediaContentsRange(0, contentsToLoad)
|
||||||
|
Log.i("$TAG [${contents.size}] media have been fetched")
|
||||||
|
|
||||||
|
mediaList.postValue(getFileModelsListFromContents(contents))
|
||||||
|
operationInProgress.postValue(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun loadMoreData(totalItemsCount: Int) {
|
||||||
|
coreContext.postOnCoreThread {
|
||||||
|
Log.i("$TAG Loading more data, current total is $totalItemsCount, max size is $totalMediaCount")
|
||||||
|
|
||||||
|
if (totalItemsCount < totalMediaCount) {
|
||||||
|
var upperBound: Int = totalItemsCount + CONTENTS_PER_PAGE
|
||||||
|
if (upperBound > totalMediaCount) {
|
||||||
|
upperBound = totalMediaCount
|
||||||
|
}
|
||||||
|
val contents = chatRoom.getMediaContentsRange(totalItemsCount, upperBound)
|
||||||
|
Log.i("$TAG [${contents.size}] contents loaded, adding them to list")
|
||||||
|
|
||||||
|
val list = arrayListOf<FileModel>()
|
||||||
|
list.addAll(mediaList.value.orEmpty())
|
||||||
|
list.addAll(getFileModelsListFromContents(contents))
|
||||||
|
mediaList.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
private fun getFileModelsListFromContents(contents: Array<Content>): ArrayList<FileModel> {
|
||||||
|
val list = arrayListOf<FileModel>()
|
||||||
|
for (mediaContent in contents) {
|
||||||
// Do not display voice recordings here, even if they are media file
|
// Do not display voice recordings here, even if they are media file
|
||||||
if (mediaContent.isVoiceRecording) continue
|
if (mediaContent.isVoiceRecording) continue
|
||||||
|
|
||||||
|
|
@ -85,14 +124,11 @@ class ConversationMediaListViewModel
|
||||||
if (path.isNotEmpty() && name.isNotEmpty()) {
|
if (path.isNotEmpty() && name.isNotEmpty()) {
|
||||||
val model =
|
val model =
|
||||||
FileModel(path, name, size, timestamp, isEncrypted, originalPath, chatRoom.isEphemeralEnabled) {
|
FileModel(path, name, size, timestamp, isEncrypted, originalPath, chatRoom.isEphemeralEnabled) {
|
||||||
openMediaEvent.postValue(Event(it))
|
openMediaEvent.postValue(Event(it))
|
||||||
}
|
}
|
||||||
list.add(model)
|
list.add(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return list
|
||||||
Log.i("$TAG [${media.size}] media have been processed")
|
|
||||||
mediaList.postValue(list)
|
|
||||||
operationInProgress.postValue(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue