Check user validity and add a code view fragment
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm
|
||||
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.GiteaService
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||
|
||||
object TeaIsWarm {
|
||||
|
||||
val service: RepositoryService by lazy {
|
||||
GiteaService()
|
||||
}
|
||||
}
|
@@ -17,9 +17,9 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_NAME
|
||||
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_OWNER
|
||||
import fr.uca.iut.clfreville2.teaiswarm.TeaIsWarm
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.CommitActivity
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.GiteaService
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -28,7 +28,7 @@ import java.io.IOException
|
||||
|
||||
class ActivityListFragment : Fragment(R.layout.activity_list) {
|
||||
|
||||
private val service = GiteaService()
|
||||
private val service = TeaIsWarm.service
|
||||
var repository: RepositoryIdentifier? = null
|
||||
var sha: String? = null
|
||||
|
||||
|
@@ -0,0 +1,33 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_NAME
|
||||
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_OWNER
|
||||
import fr.uca.iut.clfreville2.teaiswarm.TeaIsWarm
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class CodeViewFragment : Fragment(R.layout.code_view_fragment) {
|
||||
|
||||
private lateinit var content: TextView
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val service = TeaIsWarm.service
|
||||
val bundle = requireArguments()
|
||||
val repository = RepositoryIdentifier(
|
||||
bundle.getString(REPOSITORY_OWNER)!!,
|
||||
bundle.getString(REPOSITORY_NAME)!!
|
||||
)
|
||||
content = view.findViewById(R.id.code_content_view)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val contents = service.retrieveFileContents(repository, bundle.getString(FILE_PATH)!!)
|
||||
content.text = contents.content
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,16 +10,16 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.*
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.FileType
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.VersionedFile
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.GiteaService
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
const val FILE_PATH = "file_path"
|
||||
|
||||
class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
|
||||
private val service = GiteaService()
|
||||
private val service = TeaIsWarm.service
|
||||
private lateinit var repositoryName: TextView
|
||||
private lateinit var repositoryDescription: TextView
|
||||
private lateinit var activity: Button
|
||||
@@ -61,6 +61,14 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
REPOSITORY_NAME to currentRepositoryName,
|
||||
FILE_PATH to (currentFilePath ?: "") + file.name
|
||||
)
|
||||
findNavController().navigate(R.id.repository_details_fragment, bundle)
|
||||
when (file.type) {
|
||||
FileType.FILE -> {
|
||||
findNavController().navigate(R.id.code_view_fragment, bundle)
|
||||
}
|
||||
FileType.DIR -> {
|
||||
findNavController().navigate(R.id.repository_details_fragment, bundle)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,9 +12,9 @@ import androidx.paging.*
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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.network.GiteaService
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -23,7 +23,7 @@ import java.io.IOException
|
||||
|
||||
class RepositoryListFragment(private val username: String, private val onClick: (Repository) -> Unit) : Fragment(R.layout.repository_list) {
|
||||
|
||||
private val service = GiteaService()
|
||||
private val service = TeaIsWarm.service
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
@@ -5,11 +5,16 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.edit
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
import fr.uca.iut.clfreville2.teaiswarm.TeaIsWarm
|
||||
import fr.uca.iut.clfreville2.teaiswarm.USERNAME
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Owner
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SetupConfigFragment(private val preferences: SharedPreferences) : Fragment(R.layout.setup_config) {
|
||||
|
||||
@@ -21,10 +26,22 @@ class SetupConfigFragment(private val preferences: SharedPreferences) : Fragment
|
||||
usernameInput = view.findViewById(R.id.username_input)
|
||||
confirmButton = view.findViewById(R.id.configure_button)
|
||||
confirmButton.setOnClickListener {
|
||||
preferences.edit {
|
||||
putString(USERNAME, usernameInput.text.toString())
|
||||
val username = usernameInput.text.toString()
|
||||
lifecycleScope.launch {
|
||||
val owner = TeaIsWarm.service.searchOwner(username)
|
||||
if (owner is Owner) {
|
||||
preferences.edit {
|
||||
putString(USERNAME, usernameInput.text.toString())
|
||||
}
|
||||
view.findNavController().navigate(R.id.repository_list_fragment)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
view.context,
|
||||
resources.getText(R.string.owner_not_found),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
view.findNavController().navigate(R.id.repository_list_fragment)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
data class FileContent(val type: FileType, val size: Int, val content: String, val last_commit_sha: String)
|
@@ -8,6 +8,7 @@ import fr.uca.iut.clfreville2.teaiswarm.model.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||
import retrofit2.http.GET
|
||||
@@ -15,6 +16,8 @@ import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import java.util.*
|
||||
|
||||
const val HTTP_NOT_FOUND = 404;
|
||||
|
||||
interface GiteaApiService {
|
||||
|
||||
@GET("users/{username}/repos")
|
||||
@@ -25,6 +28,12 @@ interface GiteaApiService {
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents/{filePath}")
|
||||
suspend fun listFileContents(@Path("owner") owner: String, @Path("repo") repo: String, @Path("filePath") filePath: String): List<VersionedFile>
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents/{filePath}")
|
||||
suspend fun retrieveFileContents(@Path("owner") owner: String, @Path("repo") repo: String, @Path("filePath") filePath: String): FileContent
|
||||
|
||||
@GET("users/{owner}")
|
||||
suspend fun searchOwner(@Path("owner") owner: String): Owner?
|
||||
}
|
||||
|
||||
class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
||||
@@ -54,6 +63,23 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
||||
override suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List<VersionedFile> = withContext(Dispatchers.IO) {
|
||||
handle.listFileContents(repository.identifier.owner, repository.identifier.name, filePath)
|
||||
}
|
||||
|
||||
override suspend fun retrieveFileContents(
|
||||
repository: RepositoryIdentifiable,
|
||||
filePath: String
|
||||
): FileContent = withContext(Dispatchers.IO) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val CODEFIRST_API_BASE = "https://codefirst.iut.uca.fr/git/api/v1/"
|
||||
|
@@ -9,4 +9,8 @@ interface RepositoryService {
|
||||
suspend fun listCommits(repository: RepositoryIdentifiable, sha: String?, page: Int): List<CommitActivity>
|
||||
|
||||
suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List<VersionedFile>
|
||||
|
||||
suspend fun retrieveFileContents(repository: RepositoryIdentifiable, filePath: String): FileContent
|
||||
|
||||
suspend fun searchOwner(owner: String): Owner?
|
||||
}
|
||||
|
@@ -55,6 +55,20 @@ class StubRepositoryService : RepositoryService {
|
||||
"CONVENTIONS.md",
|
||||
"README.md"
|
||||
).map { VersionedFile(it, if (it.contains(".")) { FileType.FILE } else { FileType.DIR }) }
|
||||
|
||||
// See KT-2425
|
||||
override suspend fun retrieveFileContents(
|
||||
repository: RepositoryIdentifiable,
|
||||
filePath: String
|
||||
) = FileContent(
|
||||
FileType.FILE, 82, """
|
||||
#!/bin/bash
|
||||
container_id=$(docker run --detach nginx)
|
||||
docker stop ${'$'}container_id""", randomCommitSha()
|
||||
)
|
||||
|
||||
override suspend fun searchOwner(owner: String): Owner =
|
||||
Owner(1, owner)
|
||||
}
|
||||
|
||||
val CHAR_POOL = "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
|
||||
|
11
app/src/main/res/layout/code_view_fragment.xml
Normal file
11
app/src/main/res/layout/code_view_fragment.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/code_content_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
@@ -4,20 +4,27 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username_input"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@+id/configure_button"
|
||||
android:autofillHints="" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/configure_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/configure"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints=""
|
||||
app:layout_constraintBottom_toTopOf="@+id/configure_button" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/configure_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/configure" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@@ -28,4 +28,8 @@
|
||||
android:id="@+id/repository_details_fragment"
|
||||
android:name="fr.uca.iut.clfreville2.teaiswarm.fragment.RepositoryDetailsFragment"
|
||||
android:label="RepositoryDetailsFragment" />
|
||||
<fragment
|
||||
android:id="@+id/code_view_fragment"
|
||||
android:name="fr.uca.iut.clfreville2.teaiswarm.fragment.CodeViewFragment"
|
||||
android:label="CodeViewFragment" />
|
||||
</navigation>
|
||||
|
@@ -14,4 +14,5 @@
|
||||
<string name="username">Username</string>
|
||||
<string name="configure">Configure</string>
|
||||
<string name="activity">Activity</string>
|
||||
<string name="owner_not_found">User not found</string>
|
||||
</resources>
|
Reference in New Issue
Block a user