Sort by various criteria
This commit is contained in:
@@ -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();
|
||||
|
Reference in New Issue
Block a user