diff --git a/app/src/main/java/com/nextcloud/talk/activities/SharedItemsActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/SharedItemsActivity.kt index d611f575f..f9661d72a 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/SharedItemsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/SharedItemsActivity.kt @@ -8,6 +8,7 @@ import androidx.core.content.res.ResourcesCompat import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.google.android.material.tabs.TabLayout import com.nextcloud.talk.R import com.nextcloud.talk.adapters.SharedItemsAdapter @@ -60,7 +61,7 @@ class SharedItemsActivity : AppCompatActivity() { SharedItemsViewModel.Factory(userEntity, roomToken, currentTab) ).get(SharedItemsViewModel::class.java) - viewModel.media.observe(this) { + viewModel.sharedItems.observe(this) { Log.d(TAG, "Items received: $it") if (currentTab == TAB_MEDIA) { @@ -71,8 +72,6 @@ class SharedItemsActivity : AppCompatActivity() { val layoutManager = GridLayoutManager(this, 4) binding.imageRecycler.layoutManager = layoutManager - - adapter.notifyDataSetChanged() } else { val adapter = SharedItemsListAdapter() adapter.items = it.items @@ -82,15 +81,22 @@ class SharedItemsActivity : AppCompatActivity() { val layoutManager = LinearLayoutManager(this) layoutManager.orientation = LinearLayoutManager.VERTICAL binding.imageRecycler.layoutManager = layoutManager - - adapter.notifyDataSetChanged() } } + + binding.imageRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (!recyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE) { + viewModel.loadNextItems() + } + } + }) } fun updateItems(type: String) { currentTab = type - viewModel.loadMediaItems(type) + viewModel.loadItems(type) } private fun initTabs() { @@ -134,13 +140,9 @@ class SharedItemsActivity : AppCompatActivity() { updateItems(tab.tag as String) } - override fun onTabUnselected(tab: TabLayout.Tab) { - // unused atm - } + override fun onTabUnselected(tab: TabLayout.Tab) = Unit - override fun onTabReselected(tab: TabLayout.Tab) { - // unused atm - } + override fun onTabReselected(tab: TabLayout.Tab) = Unit }) } diff --git a/app/src/main/java/com/nextcloud/talk/repositories/SharedItemsRepository.kt b/app/src/main/java/com/nextcloud/talk/repositories/SharedItemsRepository.kt index c6d26df2c..d908c9ee4 100644 --- a/app/src/main/java/com/nextcloud/talk/repositories/SharedItemsRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/repositories/SharedItemsRepository.kt @@ -29,12 +29,16 @@ class SharedItemsRepository { } fun media(type: String): Observable>? { + return media(type, null) + } + + fun media(type: String, lastKnownMessageId: Int?): Observable>? { val credentials = ApiUtils.getCredentials(parameters!!.userName, parameters!!.userToken) return ncApi.getSharedItems( credentials, ApiUtils.getUrlForChatSharedItems(1, parameters!!.baseUrl, parameters!!.roomToken), - type, null, null + type, lastKnownMessageId, 28 ) } diff --git a/app/src/main/java/com/nextcloud/talk/repositories/SharedMediaItems.kt b/app/src/main/java/com/nextcloud/talk/repositories/SharedMediaItems.kt index f83a5c6ea..1e3b56bae 100644 --- a/app/src/main/java/com/nextcloud/talk/repositories/SharedMediaItems.kt +++ b/app/src/main/java/com/nextcloud/talk/repositories/SharedMediaItems.kt @@ -1,7 +1,9 @@ package com.nextcloud.talk.repositories class SharedMediaItems( - val items: List, - val lastSeenId: String, + val type: String, + val items: MutableList, + var lastSeenId: Int?, + var moreItemsExisting: Boolean, val authHeader: Map ) diff --git a/app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt b/app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt index 6a90ef67c..39af56a00 100644 --- a/app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/viewmodels/SharedItemsViewModel.kt @@ -16,76 +16,109 @@ import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers import retrofit2.Response -class SharedItemsViewModel(private val repository: SharedItemsRepository, private val initialType: String) : ViewModel() { +class SharedItemsViewModel(private val repository: SharedItemsRepository, private val initialType: String) : + ViewModel() { - private val _media: MutableLiveData by lazy { + private val _sharedItems: MutableLiveData by lazy { MutableLiveData().also { - loadMediaItems(initialType) + loadItems(initialType) } } - val media: LiveData - get() = _media + val sharedItems: LiveData + get() = _sharedItems - fun loadMediaItems(type: String) { + fun loadNextItems() { + val currentSharedItems = sharedItems.value!! + if (currentSharedItems.moreItemsExisting) { + repository.media(currentSharedItems.type, currentSharedItems.lastSeenId)?.subscribeOn(Schedulers.io()) + ?.observeOn(AndroidSchedulers.mainThread()) + ?.subscribe(observer(currentSharedItems.type, false)) + } + } + + fun loadItems(type: String) { repository.media(type)?.subscribeOn(Schedulers.io()) ?.observeOn(AndroidSchedulers.mainThread()) - ?.subscribe(object : Observer> { + ?.subscribe(observer(type, true)) + } - var chatLastGiven: String = "" - val items = mutableMapOf() + private fun observer(type: String, initModel: Boolean): Observer> { + return object : Observer> { - override fun onSubscribe(d: Disposable) = Unit + var chatLastGiven: Int? = null + val items = mutableMapOf() - override fun onNext(response: Response) { + override fun onSubscribe(d: Disposable) = Unit - if (response.headers()["x-chat-last-given"] != null) { - chatLastGiven = response.headers()["x-chat-last-given"]!! - } + override fun onNext(response: Response) { - val mediaItems = response.body()!!.ocs!!.data - mediaItems?.forEach { - if (it.value.messageParameters.containsKey("file")) { - val fileParameters = it.value.messageParameters["file"]!! - - val previewAvailable = "yes".equals(fileParameters["preview-available"]!!, ignoreCase = true) - - items[it.value.id] = SharedItem( - fileParameters["id"]!!, - fileParameters["name"]!!, - fileParameters["size"]!!.toInt(), - fileParameters["path"]!!, - fileParameters["link"]!!, - fileParameters["mimetype"]!!, - previewAvailable, - repository.previewLink(fileParameters["id"]), - repository.parameters!!.userEntity - ) - } else { - Log.w(TAG, "location and deckcard are not yet supported") - } - - } + if (response.headers()["x-chat-last-given"] != null) { + chatLastGiven = response.headers()["x-chat-last-given"]!!.toInt() } - override fun onError(e: Throwable) { - Log.d(TAG, "An error occurred: $e") - } + val mediaItems = response.body()!!.ocs!!.data + mediaItems?.forEach { + if (it.value.messageParameters.containsKey("file")) { + val fileParameters = it.value.messageParameters["file"]!! - override fun onComplete() { - this@SharedItemsViewModel._media.value = + val previewAvailable = "yes".equals(fileParameters["preview-available"]!!, ignoreCase = true) + + items[it.value.id] = SharedItem( + fileParameters["id"]!!, + fileParameters["name"]!!, + fileParameters["size"]!!.toInt(), + fileParameters["path"]!!, + fileParameters["link"]!!, + fileParameters["mimetype"]!!, + previewAvailable, + repository.previewLink(fileParameters["id"]), + repository.parameters!!.userEntity + ) + } else { + Log.w(TAG, "location and deckcard are not yet supported") + } + + } + } + + override fun onError(e: Throwable) { + Log.d(TAG, "An error occurred: $e") + } + + override fun onComplete() { + + val sortedMutableItems = items.toSortedMap().values.toList().reversed().toMutableList() + val moreItemsExisting = items.count() == 28 + + if (initModel) { + this@SharedItemsViewModel._sharedItems.value = SharedMediaItems( - items.toSortedMap().values.toList().reversed(), + type, + sortedMutableItems, chatLastGiven, + moreItemsExisting, + repository.authHeader() + ) + } else { + val oldItems = this@SharedItemsViewModel._sharedItems.value!!.items + this@SharedItemsViewModel._sharedItems.value = + SharedMediaItems( + type, + (oldItems.toMutableList() + sortedMutableItems) as MutableList, + chatLastGiven, + moreItemsExisting, repository.authHeader() ) } - }) + } + } } - class Factory(val userEntity: UserEntity, val roomToken: String, private val initialType: String) : ViewModelProvider - .Factory { + class Factory(val userEntity: UserEntity, val roomToken: String, private val initialType: String) : + ViewModelProvider + .Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(SharedItemsViewModel::class.java)) { diff --git a/app/src/main/res/layout/activity_shared_items.xml b/app/src/main/res/layout/activity_shared_items.xml index 486b79e57..d6ababc24 100644 --- a/app/src/main/res/layout/activity_shared_items.xml +++ b/app/src/main/res/layout/activity_shared_items.xml @@ -1,5 +1,4 @@ - - - + android:layout_height="wrap_content"> - + app:layout_flexGrow="1" + app:layout_wrapBefore="true"> - - + + + + + \ No newline at end of file