mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-04 02:51:09 +01:00
SharedItems: show loading state when initially loading a tab, and clear remaining TODOs
Co-authored-by: Tim Krüger <t@timkrueger.me> Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
parent
5310ed3f3d
commit
05340fc466
@ -85,13 +85,13 @@ class SharedItemsActivity : AppCompatActivity() {
|
|||||||
viewModel = ViewModelProvider(this, viewModelFactory)[SharedItemsViewModel::class.java]
|
viewModel = ViewModelProvider(this, viewModelFactory)[SharedItemsViewModel::class.java]
|
||||||
|
|
||||||
viewModel.viewState.observe(this) { state ->
|
viewModel.viewState.observe(this) { state ->
|
||||||
handleEmptyView(state)
|
handleEmptyLoadingView(state)
|
||||||
when (state) {
|
when (state) {
|
||||||
is SharedItemsViewModel.LoadedState -> {
|
is SharedItemsViewModel.LoadedState -> {
|
||||||
val sharedMediaItems = state.items
|
val sharedMediaItems = state.items
|
||||||
Log.d(TAG, "Items received: $sharedMediaItems")
|
Log.d(TAG, "Items received: $sharedMediaItems")
|
||||||
|
|
||||||
val showGrid = viewModel.currentItemType == SharedItemType.MEDIA
|
val showGrid = state.selectedType == SharedItemType.MEDIA
|
||||||
val layoutManager = if (showGrid) {
|
val layoutManager = if (showGrid) {
|
||||||
GridLayoutManager(this, SPAN_COUNT)
|
GridLayoutManager(this, SPAN_COUNT)
|
||||||
} else {
|
} else {
|
||||||
@ -104,7 +104,9 @@ class SharedItemsActivity : AppCompatActivity() {
|
|||||||
binding.imageRecycler.adapter = adapter
|
binding.imageRecycler.adapter = adapter
|
||||||
binding.imageRecycler.layoutManager = layoutManager
|
binding.imageRecycler.layoutManager = layoutManager
|
||||||
}
|
}
|
||||||
is SharedItemsViewModel.TabsLoadedState -> initTabs(state.types)
|
is SharedItemsViewModel.TypesLoadedState -> {
|
||||||
|
initTabs(state.types)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
@ -120,25 +122,28 @@ class SharedItemsActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.initialize(userEntity, roomToken, SharedItemType.MEDIA)
|
viewModel.initialize(userEntity, roomToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleEmptyView(state: SharedItemsViewModel.ViewState?) {
|
private fun handleEmptyLoadingView(state: SharedItemsViewModel.ViewState?) {
|
||||||
when (state) {
|
binding.emptyContainer.emptyListViewHeadline.text = when (state) {
|
||||||
SharedItemsViewModel.NoSharedItemsState -> {
|
SharedItemsViewModel.NoSharedItemsState -> getString(R.string.nc_shared_items_description)
|
||||||
binding.emptyContainer.emptyListViewHeadline.text = getString(R.string.nc_shared_items_empty)
|
else -> getString(R.string.file_list_loading)
|
||||||
binding.emptyContainer.emptyListView.visibility = View.VISIBLE
|
|
||||||
binding.sharedItemsTabs.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
else -> {
|
binding.emptyContainer.emptyListView.visibility = when (state) {
|
||||||
binding.emptyContainer.emptyListView.visibility = View.GONE
|
SharedItemsViewModel.NoSharedItemsState, is SharedItemsViewModel.LoadingItemsState -> View.VISIBLE
|
||||||
binding.sharedItemsTabs.visibility = View.VISIBLE
|
else -> View.GONE
|
||||||
}
|
}
|
||||||
|
binding.sharedItemsTabs.visibility = when (state) {
|
||||||
|
SharedItemsViewModel.NoSharedItemsState -> View.GONE
|
||||||
|
else -> View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initTabs(sharedItemTypes: Set<SharedItemType>) {
|
private fun initTabs(sharedItemTypes: Set<SharedItemType>) {
|
||||||
|
|
||||||
|
binding.sharedItemsTabs.removeAllTabs()
|
||||||
|
|
||||||
if (sharedItemTypes.contains(SharedItemType.MEDIA)) {
|
if (sharedItemTypes.contains(SharedItemType.MEDIA)) {
|
||||||
val tabMedia: TabLayout.Tab = binding.sharedItemsTabs.newTab()
|
val tabMedia: TabLayout.Tab = binding.sharedItemsTabs.newTab()
|
||||||
tabMedia.tag = SharedItemType.MEDIA
|
tabMedia.tag = SharedItemType.MEDIA
|
||||||
@ -190,15 +195,13 @@ class SharedItemsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
binding.sharedItemsTabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
binding.sharedItemsTabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
viewModel.loadItems(tab.tag as SharedItemType)
|
viewModel.initialLoadItems(tab.tag as SharedItemType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
|
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
|
||||||
|
|
||||||
override fun onTabReselected(tab: TabLayout.Tab) = Unit
|
override fun onTabReselected(tab: TabLayout.Tab) = Unit
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.loadItems(SharedItemType.MEDIA)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -42,90 +42,29 @@ class SharedItemsViewModel @Inject constructor(
|
|||||||
ViewModel() {
|
ViewModel() {
|
||||||
|
|
||||||
private lateinit var repositoryParameters: SharedItemsRepository.Parameters
|
private lateinit var repositoryParameters: SharedItemsRepository.Parameters
|
||||||
private lateinit var _currentItemType: SharedItemType
|
|
||||||
val currentItemType: SharedItemType
|
|
||||||
get() = _currentItemType
|
|
||||||
|
|
||||||
// items
|
|
||||||
sealed interface ViewState
|
sealed interface ViewState
|
||||||
object InitialState : ViewState
|
object InitialState : ViewState
|
||||||
object NoSharedItemsState : ViewState
|
object NoSharedItemsState : ViewState
|
||||||
open class TabsLoadedState(val types: Set<SharedItemType>) : ViewState
|
open class TypesLoadedState(val types: Set<SharedItemType>, val selectedType: SharedItemType) : ViewState
|
||||||
class LoadedState(types: Set<SharedItemType>, val items: SharedMediaItems) : TabsLoadedState(types)
|
class LoadingItemsState(types: Set<SharedItemType>, selectedType: SharedItemType) :
|
||||||
|
TypesLoadedState(types, selectedType)
|
||||||
|
|
||||||
|
class LoadedState(types: Set<SharedItemType>, selectedType: SharedItemType, val items: SharedMediaItems) :
|
||||||
|
TypesLoadedState(types, selectedType)
|
||||||
|
|
||||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||||
val viewState: LiveData<ViewState>
|
val viewState: LiveData<ViewState>
|
||||||
get() = _viewState
|
get() = _viewState
|
||||||
|
|
||||||
fun loadNextItems() {
|
fun initialize(userEntity: UserEntity, roomToken: String) {
|
||||||
when (val currentState = _viewState.value) {
|
repositoryParameters = SharedItemsRepository.Parameters(
|
||||||
is LoadedState -> {
|
userEntity.userId,
|
||||||
val currentSharedItems = currentState.items
|
userEntity.token,
|
||||||
if (currentSharedItems.moreItemsExisting) {
|
userEntity.baseUrl,
|
||||||
repository.media(repositoryParameters, _currentItemType, currentSharedItems.lastSeenId)
|
roomToken
|
||||||
?.subscribeOn(Schedulers.io())
|
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
?.subscribe(observer(_currentItemType, false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadItems(type: SharedItemType) {
|
|
||||||
|
|
||||||
_currentItemType = type
|
|
||||||
|
|
||||||
repository.media(repositoryParameters, type)?.subscribeOn(Schedulers.io())
|
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
?.subscribe(observer(type, true))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun observer(type: SharedItemType, initModel: Boolean): Observer<SharedMediaItems> {
|
|
||||||
return object : Observer<SharedMediaItems> {
|
|
||||||
|
|
||||||
var newSharedItems: SharedMediaItems? = null
|
|
||||||
|
|
||||||
override fun onSubscribe(d: Disposable) = Unit
|
|
||||||
|
|
||||||
override fun onNext(response: SharedMediaItems) {
|
|
||||||
newSharedItems = response
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
Log.d(TAG, "An error occurred: $e")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {
|
|
||||||
val items = newSharedItems!!
|
|
||||||
// todo replace initmodel with tabsloadedstate
|
|
||||||
if (initModel) {
|
|
||||||
setCurrentState(items)
|
|
||||||
} else {
|
|
||||||
val state = this@SharedItemsViewModel._viewState.value as LoadedState
|
|
||||||
val oldItems = state.items.items
|
|
||||||
val newItems =
|
|
||||||
SharedMediaItems(
|
|
||||||
oldItems + newSharedItems!!.items,
|
|
||||||
newSharedItems!!.lastSeenId,
|
|
||||||
newSharedItems!!.moreItemsExisting
|
|
||||||
)
|
)
|
||||||
setCurrentState(newItems)
|
loadAvailableTypes()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setCurrentState(items: SharedMediaItems) {
|
|
||||||
when (val state = this@SharedItemsViewModel._viewState.value) {
|
|
||||||
is TabsLoadedState -> {
|
|
||||||
this@SharedItemsViewModel._viewState.value = LoadedState(
|
|
||||||
state.types,
|
|
||||||
items
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAvailableTypes() {
|
private fun loadAvailableTypes() {
|
||||||
@ -150,22 +89,88 @@ class SharedItemsViewModel @Inject constructor(
|
|||||||
if (newTypes.isNullOrEmpty()) {
|
if (newTypes.isNullOrEmpty()) {
|
||||||
this@SharedItemsViewModel._viewState.value = NoSharedItemsState
|
this@SharedItemsViewModel._viewState.value = NoSharedItemsState
|
||||||
} else {
|
} else {
|
||||||
this@SharedItemsViewModel._viewState.value = TabsLoadedState(newTypes)
|
val selectedType = chooseInitialType(newTypes)
|
||||||
|
this@SharedItemsViewModel._viewState.value =
|
||||||
|
TypesLoadedState(newTypes, selectedType)
|
||||||
|
initialLoadItems(selectedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cleanup
|
private fun chooseInitialType(newTypes: Set<SharedItemType>): SharedItemType = when {
|
||||||
fun initialize(userEntity: UserEntity, roomToken: String, initialType: SharedItemType) {
|
newTypes.contains(SharedItemType.MEDIA) -> SharedItemType.MEDIA
|
||||||
repositoryParameters = SharedItemsRepository.Parameters(
|
else -> newTypes.toList().first()
|
||||||
userEntity.userId,
|
}
|
||||||
userEntity.token,
|
|
||||||
userEntity.baseUrl,
|
fun initialLoadItems(type: SharedItemType) {
|
||||||
roomToken
|
val state = _viewState.value
|
||||||
|
if (state is TypesLoadedState) {
|
||||||
|
_viewState.value = LoadingItemsState(state.types, type)
|
||||||
|
repository.media(repositoryParameters, type)?.subscribeOn(Schedulers.io())
|
||||||
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
?.subscribe(SharedMediaItemsObserver())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadNextItems() {
|
||||||
|
when (val currentState = _viewState.value) {
|
||||||
|
is LoadedState -> {
|
||||||
|
val currentSharedItems = currentState.items
|
||||||
|
if (currentSharedItems.moreItemsExisting) {
|
||||||
|
repository.media(repositoryParameters, currentState.selectedType, currentSharedItems.lastSeenId)
|
||||||
|
?.subscribeOn(Schedulers.io())
|
||||||
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
?.subscribe(SharedMediaItemsObserver())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class SharedMediaItemsObserver : Observer<SharedMediaItems> {
|
||||||
|
|
||||||
|
var newSharedItems: SharedMediaItems? = null
|
||||||
|
|
||||||
|
override fun onSubscribe(d: Disposable) = Unit
|
||||||
|
|
||||||
|
override fun onNext(response: SharedMediaItems) {
|
||||||
|
newSharedItems = response
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
Log.d(TAG, "An error occurred: $e")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
val items = newSharedItems!!
|
||||||
|
val state = this@SharedItemsViewModel._viewState.value
|
||||||
|
if (state is LoadedState) {
|
||||||
|
val oldItems = state.items.items
|
||||||
|
val newItems =
|
||||||
|
SharedMediaItems(
|
||||||
|
oldItems + newSharedItems!!.items,
|
||||||
|
newSharedItems!!.lastSeenId,
|
||||||
|
newSharedItems!!.moreItemsExisting
|
||||||
)
|
)
|
||||||
_currentItemType = initialType
|
setCurrentState(newItems)
|
||||||
loadAvailableTypes()
|
} else {
|
||||||
|
setCurrentState(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setCurrentState(items: SharedMediaItems) {
|
||||||
|
when (val state = this@SharedItemsViewModel._viewState.value) {
|
||||||
|
is TypesLoadedState -> {
|
||||||
|
this@SharedItemsViewModel._viewState.value = LoadedState(
|
||||||
|
state.types,
|
||||||
|
state.selectedType,
|
||||||
|
items
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
Loading…
Reference in New Issue
Block a user