2019-07-19 20:10:20 +02:00
|
|
|
package com.keylesspalace.tusky.components.search.fragments
|
|
|
|
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.view.View
|
|
|
|
import androidx.fragment.app.Fragment
|
2020-12-27 21:25:35 +01:00
|
|
|
import androidx.fragment.app.activityViewModels
|
2021-06-17 18:54:56 +02:00
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
|
import androidx.paging.LoadState
|
|
|
|
import androidx.paging.PagingData
|
|
|
|
import androidx.paging.PagingDataAdapter
|
2019-07-19 20:10:20 +02:00
|
|
|
import androidx.recyclerview.widget.DividerItemDecoration
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
2020-01-13 13:57:44 +01:00
|
|
|
import androidx.recyclerview.widget.SimpleItemAnimator
|
2019-07-19 20:10:20 +02:00
|
|
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
|
|
import com.google.android.material.snackbar.Snackbar
|
|
|
|
import com.keylesspalace.tusky.AccountActivity
|
|
|
|
import com.keylesspalace.tusky.BottomSheetActivity
|
|
|
|
import com.keylesspalace.tusky.R
|
|
|
|
import com.keylesspalace.tusky.ViewTagActivity
|
|
|
|
import com.keylesspalace.tusky.components.search.SearchViewModel
|
2021-03-13 21:27:20 +01:00
|
|
|
import com.keylesspalace.tusky.databinding.FragmentSearchBinding
|
2019-07-19 20:10:20 +02:00
|
|
|
import com.keylesspalace.tusky.di.Injectable
|
|
|
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
|
|
|
import com.keylesspalace.tusky.interfaces.LinkListener
|
2021-06-17 18:54:56 +02:00
|
|
|
import com.keylesspalace.tusky.util.viewBinding
|
|
|
|
import com.keylesspalace.tusky.util.visible
|
|
|
|
import kotlinx.coroutines.flow.Flow
|
|
|
|
import kotlinx.coroutines.flow.collectLatest
|
|
|
|
import kotlinx.coroutines.launch
|
2019-07-19 20:10:20 +02:00
|
|
|
import javax.inject.Inject
|
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
abstract class SearchFragment<T: Any> : Fragment(R.layout.fragment_search),
|
2019-07-19 20:10:20 +02:00
|
|
|
LinkListener, Injectable, SwipeRefreshLayout.OnRefreshListener {
|
2019-11-17 20:58:54 +01:00
|
|
|
|
2019-07-19 20:10:20 +02:00
|
|
|
@Inject
|
|
|
|
lateinit var viewModelFactory: ViewModelFactory
|
|
|
|
|
2020-12-27 21:25:35 +01:00
|
|
|
protected val viewModel: SearchViewModel by activityViewModels { viewModelFactory }
|
2020-02-25 19:49:41 +01:00
|
|
|
|
2021-03-13 21:27:20 +01:00
|
|
|
protected val binding by viewBinding(FragmentSearchBinding::bind)
|
|
|
|
|
2020-02-25 19:49:41 +01:00
|
|
|
private var snackbarErrorRetry: Snackbar? = null
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
abstract fun createAdapter(): PagingDataAdapter<T, *>
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
abstract val data: Flow<PagingData<T>>
|
|
|
|
protected lateinit var adapter: PagingDataAdapter<T, *>
|
|
|
|
|
|
|
|
private var currentQuery: String = ""
|
2019-07-19 20:10:20 +02:00
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
initAdapter()
|
|
|
|
setupSwipeRefreshLayout()
|
|
|
|
subscribeObservables()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun setupSwipeRefreshLayout() {
|
2021-03-13 21:27:20 +01:00
|
|
|
binding.swipeRefreshLayout.setOnRefreshListener(this)
|
|
|
|
binding.swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
2019-07-19 20:10:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun subscribeObservables() {
|
2021-06-17 18:54:56 +02:00
|
|
|
viewLifecycleOwner.lifecycleScope.launch {
|
|
|
|
data.collectLatest { pagingData ->
|
|
|
|
adapter.submitData(pagingData)
|
|
|
|
}
|
2020-10-25 18:36:00 +01:00
|
|
|
}
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
adapter.addLoadStateListener { loadState ->
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
if (loadState.refresh is LoadState.Error) {
|
2020-01-13 13:57:44 +01:00
|
|
|
showError()
|
|
|
|
}
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
val isNewSearch = currentQuery != viewModel.currentQuery
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
binding.searchProgressBar.visible(loadState.refresh == LoadState.Loading && isNewSearch && !binding.swipeRefreshLayout.isRefreshing)
|
|
|
|
binding.searchRecyclerView.visible(loadState.refresh is LoadState.NotLoading || !isNewSearch || binding.swipeRefreshLayout.isRefreshing)
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
if (loadState.refresh != LoadState.Loading) {
|
|
|
|
binding.swipeRefreshLayout.isRefreshing = false
|
|
|
|
currentQuery = viewModel.currentQuery
|
2020-01-13 13:57:44 +01:00
|
|
|
}
|
2019-07-19 20:10:20 +02:00
|
|
|
|
2021-06-17 18:54:56 +02:00
|
|
|
binding.progressBarBottom.visible(loadState.append == LoadState.Loading)
|
|
|
|
|
|
|
|
binding.searchNoResultsText.visible(loadState.refresh is LoadState.NotLoading && adapter.itemCount == 0 && viewModel.currentQuery.isNotEmpty())
|
|
|
|
}
|
2019-07-19 20:10:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun initAdapter() {
|
2021-03-13 21:27:20 +01:00
|
|
|
binding.searchRecyclerView.addItemDecoration(DividerItemDecoration(binding.searchRecyclerView.context, DividerItemDecoration.VERTICAL))
|
|
|
|
binding.searchRecyclerView.layoutManager = LinearLayoutManager(binding.searchRecyclerView.context)
|
2019-07-19 20:10:20 +02:00
|
|
|
adapter = createAdapter()
|
2021-03-13 21:27:20 +01:00
|
|
|
binding.searchRecyclerView.adapter = adapter
|
|
|
|
binding.searchRecyclerView.setHasFixedSize(true)
|
|
|
|
(binding.searchRecyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
2019-07-19 20:10:20 +02:00
|
|
|
}
|
|
|
|
|
2020-01-13 13:57:44 +01:00
|
|
|
private fun showError() {
|
2019-07-19 20:10:20 +02:00
|
|
|
if (snackbarErrorRetry?.isShown != true) {
|
2021-03-13 21:27:20 +01:00
|
|
|
snackbarErrorRetry = Snackbar.make(binding.root, R.string.failed_search, Snackbar.LENGTH_INDEFINITE)
|
2019-07-19 20:10:20 +02:00
|
|
|
snackbarErrorRetry?.setAction(R.string.action_retry) {
|
|
|
|
snackbarErrorRetry = null
|
2021-06-17 18:54:56 +02:00
|
|
|
adapter.retry()
|
2019-07-19 20:10:20 +02:00
|
|
|
}
|
|
|
|
snackbarErrorRetry?.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onViewAccount(id: String) = startActivity(AccountActivity.getIntent(requireContext(), id))
|
|
|
|
|
|
|
|
override fun onViewTag(tag: String) = startActivity(ViewTagActivity.getIntent(requireContext(), tag))
|
|
|
|
|
|
|
|
override fun onViewUrl(url: String) {
|
|
|
|
bottomSheetActivity?.viewUrl(url)
|
|
|
|
}
|
|
|
|
|
2019-09-12 20:02:30 +02:00
|
|
|
protected val bottomSheetActivity
|
2020-01-13 13:57:44 +01:00
|
|
|
get() = (activity as? BottomSheetActivity)
|
2019-07-19 20:10:20 +02:00
|
|
|
|
|
|
|
override fun onRefresh() {
|
2021-06-17 18:54:56 +02:00
|
|
|
adapter.refresh()
|
2019-07-19 20:10:20 +02:00
|
|
|
}
|
|
|
|
}
|