Răsfoiți Sursa

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>
Álvaro Brey 3 ani în urmă
părinte
comite
05340fc466

+ 21 - 18
app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt

@@ -85,13 +85,13 @@ class SharedItemsActivity : AppCompatActivity() {
         viewModel = ViewModelProvider(this, viewModelFactory)[SharedItemsViewModel::class.java]
 
         viewModel.viewState.observe(this) { state ->
-            handleEmptyView(state)
+            handleEmptyLoadingView(state)
             when (state) {
                 is SharedItemsViewModel.LoadedState -> {
                     val sharedMediaItems = state.items
                     Log.d(TAG, "Items received: $sharedMediaItems")
 
-                    val showGrid = viewModel.currentItemType == SharedItemType.MEDIA
+                    val showGrid = state.selectedType == SharedItemType.MEDIA
                     val layoutManager = if (showGrid) {
                         GridLayoutManager(this, SPAN_COUNT)
                     } else {
@@ -104,7 +104,9 @@ class SharedItemsActivity : AppCompatActivity() {
                     binding.imageRecycler.adapter = adapter
                     binding.imageRecycler.layoutManager = layoutManager
                 }
-                is SharedItemsViewModel.TabsLoadedState -> initTabs(state.types)
+                is SharedItemsViewModel.TypesLoadedState -> {
+                    initTabs(state.types)
+                }
                 else -> {
                     // noop
                 }
@@ -120,25 +122,28 @@ class SharedItemsActivity : AppCompatActivity() {
             }
         })
 
-        viewModel.initialize(userEntity, roomToken, SharedItemType.MEDIA)
+        viewModel.initialize(userEntity, roomToken)
     }
 
-    private fun handleEmptyView(state: SharedItemsViewModel.ViewState?) {
-        when (state) {
-            SharedItemsViewModel.NoSharedItemsState -> {
-                binding.emptyContainer.emptyListViewHeadline.text = getString(R.string.nc_shared_items_empty)
-                binding.emptyContainer.emptyListView.visibility = View.VISIBLE
-                binding.sharedItemsTabs.visibility = View.GONE
-            }
-            else -> {
-                binding.emptyContainer.emptyListView.visibility = View.GONE
-                binding.sharedItemsTabs.visibility = View.VISIBLE
-            }
+    private fun handleEmptyLoadingView(state: SharedItemsViewModel.ViewState?) {
+        binding.emptyContainer.emptyListViewHeadline.text = when (state) {
+            SharedItemsViewModel.NoSharedItemsState -> getString(R.string.nc_shared_items_description)
+            else -> getString(R.string.file_list_loading)
+        }
+        binding.emptyContainer.emptyListView.visibility = when (state) {
+            SharedItemsViewModel.NoSharedItemsState, is SharedItemsViewModel.LoadingItemsState -> View.VISIBLE
+            else -> View.GONE
+        }
+        binding.sharedItemsTabs.visibility = when (state) {
+            SharedItemsViewModel.NoSharedItemsState -> View.GONE
+            else -> View.VISIBLE
         }
     }
 
     private fun initTabs(sharedItemTypes: Set<SharedItemType>) {
 
+        binding.sharedItemsTabs.removeAllTabs()
+
         if (sharedItemTypes.contains(SharedItemType.MEDIA)) {
             val tabMedia: TabLayout.Tab = binding.sharedItemsTabs.newTab()
             tabMedia.tag = SharedItemType.MEDIA
@@ -190,15 +195,13 @@ class SharedItemsActivity : AppCompatActivity() {
 
         binding.sharedItemsTabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
             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 onTabReselected(tab: TabLayout.Tab) = Unit
         })
-
-        viewModel.loadItems(SharedItemType.MEDIA)
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {

+ 91 - 86
app/src/main/java/com/nextcloud/talk/shareditems/viewmodels/SharedItemsViewModel.kt

@@ -42,90 +42,29 @@ class SharedItemsViewModel @Inject constructor(
     ViewModel() {
 
     private lateinit var repositoryParameters: SharedItemsRepository.Parameters
-    private lateinit var _currentItemType: SharedItemType
-    val currentItemType: SharedItemType
-        get() = _currentItemType
 
-    // items
     sealed interface ViewState
     object InitialState : ViewState
     object NoSharedItemsState : ViewState
-    open class TabsLoadedState(val types: Set<SharedItemType>) : ViewState
-    class LoadedState(types: Set<SharedItemType>, val items: SharedMediaItems) : TabsLoadedState(types)
+    open class TypesLoadedState(val types: Set<SharedItemType>, val selectedType: SharedItemType) : ViewState
+    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)
     val viewState: LiveData<ViewState>
         get() = _viewState
 
-    fun loadNextItems() {
-        when (val currentState = _viewState.value) {
-            is LoadedState -> {
-                val currentSharedItems = currentState.items
-                if (currentSharedItems.moreItemsExisting) {
-                    repository.media(repositoryParameters, _currentItemType, currentSharedItems.lastSeenId)
-                        ?.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)
-                }
-            }
-
-            private fun setCurrentState(items: SharedMediaItems) {
-                when (val state = this@SharedItemsViewModel._viewState.value) {
-                    is TabsLoadedState -> {
-                        this@SharedItemsViewModel._viewState.value = LoadedState(
-                            state.types,
-                            items
-                        )
-                    }
-                    else -> return
-                }
-            }
-        }
+    fun initialize(userEntity: UserEntity, roomToken: String) {
+        repositoryParameters = SharedItemsRepository.Parameters(
+            userEntity.userId,
+            userEntity.token,
+            userEntity.baseUrl,
+            roomToken
+        )
+        loadAvailableTypes()
     }
 
     private fun loadAvailableTypes() {
@@ -150,22 +89,88 @@ class SharedItemsViewModel @Inject constructor(
                     if (newTypes.isNullOrEmpty()) {
                         this@SharedItemsViewModel._viewState.value = NoSharedItemsState
                     } else {
-                        this@SharedItemsViewModel._viewState.value = TabsLoadedState(newTypes)
+                        val selectedType = chooseInitialType(newTypes)
+                        this@SharedItemsViewModel._viewState.value =
+                            TypesLoadedState(newTypes, selectedType)
+                        initialLoadItems(selectedType)
                     }
                 }
             })
     }
 
-    // TODO cleanup
-    fun initialize(userEntity: UserEntity, roomToken: String, initialType: SharedItemType) {
-        repositoryParameters = SharedItemsRepository.Parameters(
-            userEntity.userId,
-            userEntity.token,
-            userEntity.baseUrl,
-            roomToken
-        )
-        _currentItemType = initialType
-        loadAvailableTypes()
+    private fun chooseInitialType(newTypes: Set<SharedItemType>): SharedItemType = when {
+        newTypes.contains(SharedItemType.MEDIA) -> SharedItemType.MEDIA
+        else -> newTypes.toList().first()
+    }
+
+    fun initialLoadItems(type: SharedItemType) {
+        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
+                    )
+                setCurrentState(newItems)
+            } 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 {