Add a spinner for the sort criteria
This commit is contained in:
@@ -2,6 +2,9 @@ package fr.uca.iut.clfreville2.teaiswarm.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Spinner
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -16,36 +19,50 @@ import fr.uca.iut.clfreville2.teaiswarm.TeaIsWarm
|
||||
import fr.uca.iut.clfreville2.teaiswarm.adapter.RepositoryListAdapter
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchSettings
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.search.SortCriteria
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class RepositoryListFragment(
|
||||
private val search: SearchSettings,
|
||||
private val initialSearch: SearchSettings,
|
||||
private val onClick: (Repository) -> Unit
|
||||
) : Fragment(R.layout.repository_list) {
|
||||
|
||||
private val service = TeaIsWarm.service
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
private var search: SearchSettings by Delegates.observable(SearchSettings()) { _, _, _ ->
|
||||
updateRepositories()
|
||||
}
|
||||
|
||||
private fun updateRepositories() {
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var pagingAdapter: RepositoryListAdapter
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView = view.findViewById(R.id.repositories_view)
|
||||
val spinner: Spinner = view.findViewById(R.id.sort_by_spinner)
|
||||
ArrayAdapter.createFromResource(
|
||||
requireContext(),
|
||||
R.array.sort_criteria,
|
||||
android.R.layout.simple_spinner_item
|
||||
).also { adapter ->
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = adapter
|
||||
}
|
||||
spinner.onItemSelectedListener = SortListener()
|
||||
|
||||
val viewModel by viewModels<RepositoryViewModel>(
|
||||
factoryProducer = {
|
||||
RepositoryViewModelFactory(
|
||||
service,
|
||||
search
|
||||
)
|
||||
service
|
||||
) { search }
|
||||
}
|
||||
)
|
||||
val pagingAdapter =
|
||||
pagingAdapter =
|
||||
RepositoryListAdapter(RepositoryListAdapter.RepositoryComparator, onClick)
|
||||
val recyclerView = requireView().findViewById<RecyclerView>(R.id.repositories_view)
|
||||
recyclerView.adapter = pagingAdapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
@@ -53,6 +70,12 @@ class RepositoryListFragment(
|
||||
pagingAdapter.submitData(pagingData)
|
||||
}
|
||||
}
|
||||
|
||||
search = initialSearch
|
||||
}
|
||||
|
||||
private fun updateRepositories() {
|
||||
pagingAdapter.refresh()
|
||||
}
|
||||
|
||||
class RepositorySource(
|
||||
@@ -84,18 +107,18 @@ class RepositoryListFragment(
|
||||
|
||||
class RepositoryViewModel(
|
||||
private val service: RepositoryService,
|
||||
private val search: SearchSettings
|
||||
private val search: () -> SearchSettings
|
||||
) : ViewModel() {
|
||||
val flow = Pager(
|
||||
PagingConfig(pageSize = 10, enablePlaceholders = true)
|
||||
) {
|
||||
RepositorySource(service, search)
|
||||
RepositorySource(service, search())
|
||||
}.flow.cachedIn(viewModelScope)
|
||||
}
|
||||
|
||||
class RepositoryViewModelFactory(
|
||||
private val service: RepositoryService,
|
||||
private val search: SearchSettings
|
||||
private val search: () -> SearchSettings
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(RepositoryViewModel::class.java)) {
|
||||
@@ -105,4 +128,14 @@ class RepositoryListFragment(
|
||||
throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
|
||||
inner class SortListener : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
search = search.copy(sort = SortCriteria.values()[position])
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
search = search.copy(sort = SortCriteria.ALPHA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -86,28 +86,35 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
||||
handle.retrieveFileContents(repository.identifier.owner, repository.identifier.name, filePath)
|
||||
}
|
||||
|
||||
override suspend fun searchOwner(owner: String): Owner? = try {
|
||||
handle.searchOwner(owner)
|
||||
} catch (ex: HttpException) {
|
||||
if (ex.code() == HTTP_NOT_FOUND) {
|
||||
null
|
||||
} else {
|
||||
throw ex
|
||||
override suspend fun searchOwner(owner: String): Owner? = withContext(Dispatchers.IO) {
|
||||
try {
|
||||
handle.searchOwner(owner)
|
||||
} catch (ex: HttpException) {
|
||||
if (ex.code() == HTTP_NOT_FOUND) {
|
||||
null
|
||||
} else {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> =
|
||||
handle.searchRepositories(
|
||||
settings.query,
|
||||
settings.userId,
|
||||
settings.teamId,
|
||||
settings.starredBy,
|
||||
settings.mode?.toString()?.lowercase(),
|
||||
settings.sort.toString().lowercase(),
|
||||
settings.order.toString().lowercase(),
|
||||
settings.page,
|
||||
settings.limit
|
||||
).data
|
||||
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> = withContext(Dispatchers.IO) {
|
||||
if (settings.page < 1) {
|
||||
emptyList()
|
||||
} else {
|
||||
handle.searchRepositories(
|
||||
settings.query,
|
||||
settings.userId,
|
||||
settings.teamId,
|
||||
settings.starredBy,
|
||||
settings.mode?.toString()?.lowercase(),
|
||||
settings.sort.toString().lowercase(),
|
||||
settings.order.toString().lowercase(),
|
||||
settings.page,
|
||||
settings.limit
|
||||
).data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val CODEFIRST_API_BASE = "https://codefirst.iut.uca.fr/git/api/v1/"
|
||||
|
@@ -1,9 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/sort_by_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/repositories_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
@@ -15,4 +15,12 @@
|
||||
<string name="configure">Configure</string>
|
||||
<string name="activity">Activity</string>
|
||||
<string name="owner_not_found">User not found</string>
|
||||
<string name="desc_sort">Desc</string>
|
||||
<string-array name="sort_criteria">
|
||||
<item>alpha</item>
|
||||
<item>created</item>
|
||||
<item>updated</item>
|
||||
<item>size</item>
|
||||
<item>id</item>
|
||||
</string-array>
|
||||
</resources>
|
Reference in New Issue
Block a user