diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/TeaIsWarm.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/TeaIsWarm.kt new file mode 100644 index 0000000..bd728eb --- /dev/null +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/TeaIsWarm.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/ActivityListFragment.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/ActivityListFragment.kt index 7d2d2e6..36d6200 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/ActivityListFragment.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/ActivityListFragment.kt @@ -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 diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/CodeViewFragment.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/CodeViewFragment.kt new file mode 100644 index 0000000..1c0404d --- /dev/null +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/CodeViewFragment.kt @@ -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 + } + } +} diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryDetailsFragment.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryDetailsFragment.kt index ff1b5f4..a2b4fb8 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryDetailsFragment.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryDetailsFragment.kt @@ -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 -> {} + } } } \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryListFragment.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryListFragment.kt index 7ffed64..823fddc 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryListFragment.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/RepositoryListFragment.kt @@ -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) diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/SetupConfigFragment.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/SetupConfigFragment.kt index 530b0ee..f2766e3 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/SetupConfigFragment.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/fragment/SetupConfigFragment.kt @@ -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) } } } \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/model/FileContent.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/model/FileContent.kt new file mode 100644 index 0000000..7caccae --- /dev/null +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/model/FileContent.kt @@ -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) diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/GiteaService.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/GiteaService.kt index 356dd54..7069450 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/GiteaService.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/GiteaService.kt @@ -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 + + @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 = 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/" diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/RepositoryService.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/RepositoryService.kt index ec53bcd..ed96c96 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/RepositoryService.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/RepositoryService.kt @@ -9,4 +9,8 @@ interface RepositoryService { suspend fun listCommits(repository: RepositoryIdentifiable, sha: String?, page: Int): List suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List + + suspend fun retrieveFileContents(repository: RepositoryIdentifiable, filePath: String): FileContent + + suspend fun searchOwner(owner: String): Owner? } diff --git a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/StubRepositoryService.kt b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/StubRepositoryService.kt index bb94e1b..758f6b2 100644 --- a/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/StubRepositoryService.kt +++ b/app/src/main/java/fr/uca/iut/clfreville2/teaiswarm/network/StubRepositoryService.kt @@ -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(); diff --git a/app/src/main/res/layout/code_view_fragment.xml b/app/src/main/res/layout/code_view_fragment.xml new file mode 100644 index 0000000..4efd27a --- /dev/null +++ b/app/src/main/res/layout/code_view_fragment.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/main/res/layout/setup_config.xml b/app/src/main/res/layout/setup_config.xml index 6334e1f..27694c1 100644 --- a/app/src/main/res/layout/setup_config.xml +++ b/app/src/main/res/layout/setup_config.xml @@ -4,20 +4,27 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - -