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.os.Bundle
|
||||||
import android.view.View
|
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.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModel
|
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.adapter.RepositoryListAdapter
|
||||||
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
|
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.SearchSettings
|
||||||
|
import fr.uca.iut.clfreville2.teaiswarm.model.search.SortCriteria
|
||||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
class RepositoryListFragment(
|
class RepositoryListFragment(
|
||||||
private val search: SearchSettings,
|
private val initialSearch: SearchSettings,
|
||||||
private val onClick: (Repository) -> Unit
|
private val onClick: (Repository) -> Unit
|
||||||
) : Fragment(R.layout.repository_list) {
|
) : Fragment(R.layout.repository_list) {
|
||||||
|
|
||||||
private val service = TeaIsWarm.service
|
private val service = TeaIsWarm.service
|
||||||
|
private var search: SearchSettings by Delegates.observable(SearchSettings()) { _, _, _ ->
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
updateRepositories()
|
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>(
|
val viewModel by viewModels<RepositoryViewModel>(
|
||||||
factoryProducer = {
|
factoryProducer = {
|
||||||
RepositoryViewModelFactory(
|
RepositoryViewModelFactory(
|
||||||
service,
|
service
|
||||||
search
|
) { search }
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val pagingAdapter =
|
pagingAdapter =
|
||||||
RepositoryListAdapter(RepositoryListAdapter.RepositoryComparator, onClick)
|
RepositoryListAdapter(RepositoryListAdapter.RepositoryComparator, onClick)
|
||||||
val recyclerView = requireView().findViewById<RecyclerView>(R.id.repositories_view)
|
|
||||||
recyclerView.adapter = pagingAdapter
|
recyclerView.adapter = pagingAdapter
|
||||||
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
@@ -53,6 +70,12 @@ class RepositoryListFragment(
|
|||||||
pagingAdapter.submitData(pagingData)
|
pagingAdapter.submitData(pagingData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search = initialSearch
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateRepositories() {
|
||||||
|
pagingAdapter.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
class RepositorySource(
|
class RepositorySource(
|
||||||
@@ -84,18 +107,18 @@ class RepositoryListFragment(
|
|||||||
|
|
||||||
class RepositoryViewModel(
|
class RepositoryViewModel(
|
||||||
private val service: RepositoryService,
|
private val service: RepositoryService,
|
||||||
private val search: SearchSettings
|
private val search: () -> SearchSettings
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val flow = Pager(
|
val flow = Pager(
|
||||||
PagingConfig(pageSize = 10, enablePlaceholders = true)
|
PagingConfig(pageSize = 10, enablePlaceholders = true)
|
||||||
) {
|
) {
|
||||||
RepositorySource(service, search)
|
RepositorySource(service, search())
|
||||||
}.flow.cachedIn(viewModelScope)
|
}.flow.cachedIn(viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RepositoryViewModelFactory(
|
class RepositoryViewModelFactory(
|
||||||
private val service: RepositoryService,
|
private val service: RepositoryService,
|
||||||
private val search: SearchSettings
|
private val search: () -> SearchSettings
|
||||||
) : ViewModelProvider.Factory {
|
) : ViewModelProvider.Factory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
if (modelClass.isAssignableFrom(RepositoryViewModel::class.java)) {
|
if (modelClass.isAssignableFrom(RepositoryViewModel::class.java)) {
|
||||||
@@ -105,4 +128,14 @@ class RepositoryListFragment(
|
|||||||
throw IllegalArgumentException("Unknown ViewModel class")
|
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,7 +86,8 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
|||||||
handle.retrieveFileContents(repository.identifier.owner, repository.identifier.name, filePath)
|
handle.retrieveFileContents(repository.identifier.owner, repository.identifier.name, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun searchOwner(owner: String): Owner? = try {
|
override suspend fun searchOwner(owner: String): Owner? = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
handle.searchOwner(owner)
|
handle.searchOwner(owner)
|
||||||
} catch (ex: HttpException) {
|
} catch (ex: HttpException) {
|
||||||
if (ex.code() == HTTP_NOT_FOUND) {
|
if (ex.code() == HTTP_NOT_FOUND) {
|
||||||
@@ -95,8 +96,12 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
|||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> =
|
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> = withContext(Dispatchers.IO) {
|
||||||
|
if (settings.page < 1) {
|
||||||
|
emptyList()
|
||||||
|
} else {
|
||||||
handle.searchRepositories(
|
handle.searchRepositories(
|
||||||
settings.query,
|
settings.query,
|
||||||
settings.userId,
|
settings.userId,
|
||||||
@@ -108,6 +113,8 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
|||||||
settings.page,
|
settings.page,
|
||||||
settings.limit
|
settings.limit
|
||||||
).data
|
).data
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val CODEFIRST_API_BASE = "https://codefirst.iut.uca.fr/git/api/v1/"
|
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"?>
|
<?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_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
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/repositories_view"
|
android:id="@+id/repositories_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</LinearLayout>
|
@@ -15,4 +15,12 @@
|
|||||||
<string name="configure">Configure</string>
|
<string name="configure">Configure</string>
|
||||||
<string name="activity">Activity</string>
|
<string name="activity">Activity</string>
|
||||||
<string name="owner_not_found">User not found</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>
|
</resources>
|
Reference in New Issue
Block a user