Sort by various criteria

main
Clément FRÉVILLE 2 years ago
parent e64bd7a387
commit c12c46bdd5

@ -11,6 +11,7 @@ import androidx.navigation.fragment.NavHostFragment
import fr.uca.iut.clfreville2.teaiswarm.fragment.RepositoryListFragment
import fr.uca.iut.clfreville2.teaiswarm.fragment.SetupConfigFragment
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchSettings
const val REPOSITORY_OWNER = "repository_owner"
const val REPOSITORY_NAME = "repository_name"
@ -47,10 +48,7 @@ class MainActivity : AppCompatActivity() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment =
when (className) {
RepositoryListFragment::class.java.name -> RepositoryListFragment(
preferences.getString(
USERNAME,
null
)!!, onClick
SearchSettings(), onClick
)
SetupConfigFragment::class.java.name -> SetupConfigFragment(preferences)
else -> super.instantiate(classLoader, className)

@ -15,13 +15,17 @@ import fr.uca.iut.clfreville2.teaiswarm.R
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.network.RepositoryService
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
class RepositoryListFragment(private val username: String, private val onClick: (Repository) -> Unit) : Fragment(R.layout.repository_list) {
class RepositoryListFragment(
private val search: SearchSettings,
private val onClick: (Repository) -> Unit
) : Fragment(R.layout.repository_list) {
private val service = TeaIsWarm.service
@ -35,7 +39,7 @@ class RepositoryListFragment(private val username: String, private val onClick:
factoryProducer = {
RepositoryViewModelFactory(
service,
username
search
)
}
)
@ -53,13 +57,13 @@ class RepositoryListFragment(private val username: String, private val onClick:
class RepositorySource(
private val service: RepositoryService,
private val username: String
private val search: SearchSettings
) : PagingSource<Int, Repository>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Repository> =
try {
val nextPageNumber = params.key ?: 1
val response = service.listActiveRepositories(username, nextPageNumber)
val response = service.searchRepositories(search.copy(page = nextPageNumber))
LoadResult.Page(
data = response,
prevKey = nextPageNumber - 1,
@ -80,23 +84,23 @@ class RepositoryListFragment(private val username: String, private val onClick:
class RepositoryViewModel(
private val service: RepositoryService,
private val username: String
private val search: SearchSettings
) : ViewModel() {
val flow = Pager(
PagingConfig(pageSize = 10, enablePlaceholders = true)
) {
RepositorySource(service, username)
RepositorySource(service, search)
}.flow.cachedIn(viewModelScope)
}
class RepositoryViewModelFactory(
private val service: RepositoryService,
private val username: String
private val search: SearchSettings
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(RepositoryViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return RepositoryViewModel(service, username) as T
return RepositoryViewModel(service, search) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}

@ -0,0 +1,14 @@
package fr.uca.iut.clfreville2.teaiswarm.model
import com.squareup.moshi.Json
enum class RepositoryMode {
@Json(name = "fork")
FORK,
@Json(name = "source")
SOURCE,
@Json(name = "mirror")
MIRROR,
@Json(name = "collaborative")
COLLABORATIVE,
}

@ -0,0 +1,3 @@
package fr.uca.iut.clfreville2.teaiswarm.model.search
data class SearchResults<T>(val data: List<T>)

@ -0,0 +1,15 @@
package fr.uca.iut.clfreville2.teaiswarm.model.search
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryMode
data class SearchSettings(
val query: String = "",
val userId: Int? = null,
val teamId: Int? = null,
val starredBy: Int? = null,
val mode: RepositoryMode? = null,
val sort: SortCriteria = SortCriteria.ALPHA,
val order: SortOrder = SortOrder.ASC,
val page: Int = 1,
val limit: Int = 10
)

@ -0,0 +1,16 @@
package fr.uca.iut.clfreville2.teaiswarm.model.search
import com.squareup.moshi.Json
enum class SortCriteria {
@Json(name = "alpha")
ALPHA,
@Json(name = "created")
CREATED,
@Json(name = "updated")
UPDATED,
@Json(name = "size")
SIZE,
@Json(name = "id")
ID
}

@ -0,0 +1,10 @@
package fr.uca.iut.clfreville2.teaiswarm.model.search
import com.squareup.moshi.Json
enum class SortOrder {
@Json(name = "asc")
ASC,
@Json(name = "desc")
DESC
}

@ -4,6 +4,8 @@ import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import fr.uca.iut.clfreville2.teaiswarm.model.*
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchResults
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchSettings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -16,7 +18,7 @@ import retrofit2.http.Path
import retrofit2.http.Query
import java.util.*
const val HTTP_NOT_FOUND = 404;
const val HTTP_NOT_FOUND = 404
interface GiteaApiService {
@ -34,6 +36,19 @@ interface GiteaApiService {
@GET("users/{owner}")
suspend fun searchOwner(@Path("owner") owner: String): Owner?
@GET("repos/search")
suspend fun searchRepositories(
@Query("q") query: String,
@Query("uid") uid: Int?,
@Query("team_id") teamId: Int?,
@Query("starred_by") starredBy: Int?,
@Query("mode") mode: String?,
@Query("sort") sort: String,
@Query("order") order: String,
@Query("page") page: Int,
@Query("limit") limit: Int
): SearchResults<Repository>
}
class GiteaService(private val handle: GiteaApiService) : RepositoryService {
@ -80,6 +95,19 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
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
}
private const val CODEFIRST_API_BASE = "https://codefirst.iut.uca.fr/git/api/v1/"

@ -1,6 +1,7 @@
package fr.uca.iut.clfreville2.teaiswarm.network
import fr.uca.iut.clfreville2.teaiswarm.model.*
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchSettings
interface RepositoryService {
@ -13,4 +14,6 @@ interface RepositoryService {
suspend fun retrieveFileContents(repository: RepositoryIdentifiable, filePath: String): FileContent
suspend fun searchOwner(owner: String): Owner?
suspend fun searchRepositories(settings: SearchSettings): List<Repository>
}

@ -1,6 +1,7 @@
package fr.uca.iut.clfreville2.teaiswarm.network
import fr.uca.iut.clfreville2.teaiswarm.model.*
import fr.uca.iut.clfreville2.teaiswarm.model.search.SearchSettings
import java.util.Date
import kotlin.random.Random
@ -69,6 +70,9 @@ class StubRepositoryService : RepositoryService {
override suspend fun searchOwner(owner: String): Owner =
Owner(1, owner)
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> =
listActiveRepositories(settings.query, settings.page)
}
val CHAR_POOL = "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray();

Loading…
Cancel
Save