Enhance general application style

main
Clément FRÉVILLE 2 years ago
parent e01dcf059b
commit 8577dabf76

@ -9,7 +9,7 @@ android {
defaultConfig { defaultConfig {
applicationId "fr.uca.iut.clfreville2.teaiswarm" applicationId "fr.uca.iut.clfreville2.teaiswarm"
minSdk 19 minSdk 21
targetSdk 32 targetSdk 32
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@ -58,6 +58,7 @@ dependencies {
implementation "androidx.fragment:fragment-ktx:$fragment_version" implementation "androidx.fragment:fragment-ktx:$fragment_version"
implementation "androidx.preference:preference-ktx:$preference_version" implementation "androidx.preference:preference-ktx:$preference_version"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'io.coil-kt:coil:2.3.0'
//implementation 'androidx.core:core-ktx:+' //implementation 'androidx.core:core-ktx:+'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'

@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
@ -15,6 +16,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import coil.load
import fr.uca.iut.clfreville2.teaiswarm.R import fr.uca.iut.clfreville2.teaiswarm.R
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_NAME import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_NAME
import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_OWNER import fr.uca.iut.clfreville2.teaiswarm.REPOSITORY_OWNER
@ -117,16 +119,22 @@ class ActivityListFragment : Fragment(R.layout.activity_list) {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val commitNameView: TextView private val commitNameView: TextView
private val commitAuthorView: TextView private val commitAuthorView: TextView
private val commitAuthorAvatarView: ImageView
private val commitSha: TextView
init { init {
commitNameView = view.findViewById(R.id.commit_name) commitNameView = view.findViewById(R.id.commit_name)
commitAuthorView = view.findViewById(R.id.commit_author) commitAuthorView = view.findViewById(R.id.commit_author)
commitAuthorAvatarView = view.findViewById(R.id.commit_author_avatar)
commitSha = view.findViewById(R.id.commit_sha)
} }
fun bind(commit: CommitActivity?) { fun bind(commit: CommitActivity?) {
commit?.let { commit?.let {
commitNameView.text = it.commit.message commitNameView.text = it.commit.message
commitAuthorView.text = it.commit.author.name commitAuthorView.text = it.commit.author.name
commitAuthorAvatarView.load(it.author?.avatarUrl)
commitSha.text = it.sha.substring(0, 8)
} }
} }
} }

@ -9,6 +9,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.tabs.TabLayout
import fr.uca.iut.clfreville2.teaiswarm.* import fr.uca.iut.clfreville2.teaiswarm.*
import fr.uca.iut.clfreville2.teaiswarm.model.FileType import fr.uca.iut.clfreville2.teaiswarm.model.FileType
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
@ -21,8 +22,11 @@ const val FILE_PATH = "file_path"
class RepositoryDetailsFragment : Fragment(R.layout.repository_details) { class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
private val service = TeaIsWarm.service private val service = TeaIsWarm.service
private lateinit var repositoryOwner: TextView
private lateinit var repositoryName: TextView private lateinit var repositoryName: TextView
private lateinit var repositoryDescription: TextView private lateinit var repositoryDescription: TextView
private lateinit var repositoryStars: TextView
private lateinit var repositoryForks: TextView
private lateinit var activity: Button private lateinit var activity: Button
private lateinit var versionedFiles: RecyclerView private lateinit var versionedFiles: RecyclerView
@ -32,8 +36,11 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
repositoryOwner = view.findViewById(R.id.repository_detail_owner)
repositoryName = view.findViewById(R.id.repository_detail_name) repositoryName = view.findViewById(R.id.repository_detail_name)
repositoryDescription = view.findViewById(R.id.repository_detail_description) repositoryDescription = view.findViewById(R.id.repository_detail_description)
repositoryStars = view.findViewById(R.id.repo_stars)
repositoryForks = view.findViewById(R.id.repo_forks)
activity = view.findViewById(R.id.repository_detail_activity) activity = view.findViewById(R.id.repository_detail_activity)
val bundle = requireArguments() val bundle = requireArguments()
@ -41,11 +48,20 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
currentRepositoryName = bundle.getString(REPOSITORY_NAME)!! currentRepositoryName = bundle.getString(REPOSITORY_NAME)!!
currentFilePath = bundle.getString(FILE_PATH) currentFilePath = bundle.getString(FILE_PATH)
repositoryOwner.text = currentRepositoryOwner
repositoryName.text = currentRepositoryName repositoryName.text = currentRepositoryName
val id = RepositoryIdentifier(currentRepositoryOwner, currentRepositoryName)
versionedFiles = view.findViewById(R.id.versioned_files_view) versionedFiles = view.findViewById(R.id.versioned_files_view)
lifecycleScope.launch { lifecycleScope.launch {
val repos = service.listFileContents(RepositoryIdentifier(currentRepositoryOwner, currentRepositoryName), currentFilePath ?: "") val repo = service.searchRepository(id)
repo?.let {
repositoryDescription.text = it.description
repositoryStars.text = it.stars.toString()
repositoryForks.text = it.forks.toString()
}
val repos = service.listFileContents(id, currentFilePath ?: "")
versionedFiles.adapter = FileListAdapter(repos) { versionedFiles.adapter = FileListAdapter(repos) {
file -> adapterOnClick(file) file -> adapterOnClick(file)
} }
@ -54,6 +70,11 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
activity.setOnClickListener { activity.setOnClickListener {
findNavController().navigate(R.id.activity_list_fragment, bundle) findNavController().navigate(R.id.activity_list_fragment, bundle)
} }
val tabLayout = view.findViewById<TabLayout>(R.id.tabs)
resources.getStringArray(R.array.repository_tabs).forEach {
tabLayout.addTab(tabLayout.newTab().setText(it))
}
} }
private fun adapterOnClick(file: VersionedFile) { private fun adapterOnClick(file: VersionedFile) {

@ -1,3 +1,5 @@
package fr.uca.iut.clfreville2.teaiswarm.model package fr.uca.iut.clfreville2.teaiswarm.model
data class Owner(val id: Int, val login: String) import com.squareup.moshi.Json
data class Owner(val id: Int, val login: String, @Json(name = "avatar_url") val avatarUrl: String = "")

@ -37,6 +37,9 @@ interface GiteaApiService {
@GET("users/{owner}") @GET("users/{owner}")
suspend fun searchOwner(@Path("owner") owner: String): Owner? suspend fun searchOwner(@Path("owner") owner: String): Owner?
@GET("repos/{owner}/{repo}")
suspend fun searchRepository(@Path("owner") owner: String, @Path("repo") repo: String): Repository?
@GET("repos/search") @GET("repos/search")
suspend fun searchRepositories( suspend fun searchRepositories(
@Query("q") query: String, @Query("q") query: String,
@ -98,6 +101,18 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
} }
} }
override suspend fun searchRepository(repository: RepositoryIdentifiable): Repository? = withContext(Dispatchers.IO) {
try {
handle.searchRepository(repository.identifier.owner, repository.identifier.name)
} catch (ex: HttpException) {
if (ex.code() == HTTP_NOT_FOUND) {
null
} else {
throw ex
}
}
}
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> = withContext(Dispatchers.IO) { override suspend fun searchRepositories(settings: SearchSettings): List<Repository> = withContext(Dispatchers.IO) {
if (settings.page < 1) { if (settings.page < 1) {
emptyList() emptyList()

@ -15,5 +15,7 @@ interface RepositoryService {
suspend fun searchOwner(owner: String): Owner? suspend fun searchOwner(owner: String): Owner?
suspend fun searchRepository(repository: RepositoryIdentifiable): Repository?
suspend fun searchRepositories(settings: SearchSettings): List<Repository> suspend fun searchRepositories(settings: SearchSettings): List<Repository>
} }

@ -71,6 +71,8 @@ class StubRepositoryService : RepositoryService {
override suspend fun searchOwner(owner: String): Owner = override suspend fun searchOwner(owner: String): Owner =
Owner(1, owner) Owner(1, owner)
override suspend fun searchRepository(repository: RepositoryIdentifiable): Repository? = null
override suspend fun searchRepositories(settings: SearchSettings): List<Repository> = override suspend fun searchRepositories(settings: SearchSettings): List<Repository> =
listActiveRepositories(settings.query, settings.page) listActiveRepositories(settings.query, settings.page)
} }

@ -1,27 +1,57 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingHorizontal="@dimen/row_item_margin_horizontal" android:paddingHorizontal="@dimen/row_item_margin_horizontal"
android:paddingTop="@dimen/row_item_margin_vertical"> android:paddingTop="4dp"
android:orientation="vertical">
<TextView <TextView
android:id="@+id/commit_name" android:id="@+id/commit_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="?android:textColorPrimary" tools:text="Initial commit" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView <LinearLayout
android:id="@+id/commit_author" android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="0dp" android:gravity="center_vertical"
android:paddingVertical="@dimen/row_item_margin_vertical" android:orientation="horizontal">
android:text="@string/unknown" <LinearLayout
android:textSize="@dimen/repo_description_size" android:layout_width="wrap_content"
app:layout_constraintStart_toStartOf="parent" android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/commit_name" /> android:layout_weight="1"
</androidx.constraintlayout.widget.ConstraintLayout> android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
android:id="@+id/commitAuthorAvatarFrame"
android:layout_width="@dimen/profile_image_size"
android:layout_height="@dimen/profile_image_size"
app:cardCornerRadius="12dp">
<ImageView
android:id="@+id/commit_author_avatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/unknown"
android:layout_marginEnd="4dp"
tools:srcCompat="@tools:sample/avatars" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/commit_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="anonymous"/>
</LinearLayout>
<TextView
android:id="@+id/commit_sha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:alpha=".8"
android:gravity="center_vertical"
tools:text="3d93bf0fda"/>
</LinearLayout>
</LinearLayout>

@ -3,29 +3,117 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"> android:orientation="vertical">
<TextView <com.google.android.material.tabs.TabLayout
android:id="@+id/repository_detail_name" android:id="@+id/tabs"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="24dp" app:tabMode="scrollable" />
android:paddingBottom="24dp"
android:text="@string/repository_name"
android:textAlignment="center" />
<TextView <LinearLayout
android:id="@+id/repository_detail_description" android:padding="8dp"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:text="@string/repository_description"
android:padding="16dp" />
<Button <LinearLayout
android:id="@+id/repository_detail_activity" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:orientation="horizontal">
android:text="@string/activity" />
<TextView
android:id="@+id/repository_detail_owner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
android:text="/"
android:textSize="22sp"
android:textStyle="bold"
tools:ignore="HardcodedText"/>
<TextView
android:id="@+id/repository_detail_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:textSize="22sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/repository_detail_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/fab_margin"
android:autoLink="web"
android:ellipsize="end"
android:maxLines="3"
android:text="@string/repository_description"
android:textSize="16sp"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/repository_detail_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/activity"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/star"
android:layout_width="0dp"
android:layout_marginVertical="@dimen/row_item_margin_vertical"
android:layout_height="wrap_content"
android:src="@drawable/ic_star"
app:layout_constraintEnd_toStartOf="@+id/repo_stars"
app:layout_constraintBottom_toBottomOf="@+id/repo_stars"
app:layout_constraintTop_toTopOf="@+id/repo_stars" />
<TextView
android:id="@+id/repo_stars"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/row_item_margin_vertical"
android:textSize="@dimen/repo_description_size"
app:layout_constraintEnd_toStartOf="@id/forks"
app:layout_constraintBaseline_toBaselineOf="@+id/repo_forks"
tools:text="30" />
<ImageView
android:id="@+id/forks"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/row_item_margin_vertical"
android:src="@drawable/ic_git_branch"
app:layout_constraintEnd_toStartOf="@+id/repo_forks"
app:layout_constraintBottom_toBottomOf="@+id/repo_forks"
app:layout_constraintTop_toTopOf="@+id/repo_forks" />
<TextView
android:id="@+id/repo_forks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="@dimen/row_item_margin_vertical"
android:textSize="@dimen/repo_description_size"
app:layout_constraintEnd_toEndOf="parent"
tools:text="30" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/versioned_files_view" android:id="@+id/versioned_files_view"

@ -1,30 +1,37 @@
<?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" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent" android:padding="@dimen/fab_margin">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" <TextView
app:layout_constraintTop_toTopOf="parent"> android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/login_start"
android:textSize="@dimen/text_size"
android:gravity="start" />
<EditText <EditText
android:id="@+id/username_input" android:id="@+id/username_input"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autofillHints="" android:hint="@string/username"
app:layout_constraintBottom_toTopOf="@+id/configure_button" /> android:autofillHints="username"
android:inputType="textEmailAddress" />
<Button <Button
android:id="@+id/configure_button" android:id="@+id/configure_button"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/configure" /> android:text="@string/login" />
</LinearLayout> </LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -7,5 +7,7 @@
<dimen name="repo_icon_size">24dp</dimen> <dimen name="repo_icon_size">24dp</dimen>
<dimen name="loading_progress_bar_size">36dp</dimen> <dimen name="loading_progress_bar_size">36dp</dimen>
<dimen name="placeholder_item_height">32dp</dimen> <dimen name="placeholder_item_height">32dp</dimen>
<dimen name="text_size">16sp</dimen>
<dimen name="error_text_size">24sp</dimen> <dimen name="error_text_size">24sp</dimen>
<dimen name="profile_image_size">24dp</dimen>
</resources> </resources>

@ -13,10 +13,12 @@
<string name="unknown">Unknown</string> <string name="unknown">Unknown</string>
<string name="username">Username</string> <string name="username">Username</string>
<string name="configure">Configure</string> <string name="configure">Configure</string>
<string name="login">Login</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="asc_sort">Asc</string> <string name="asc_sort">Asc</string>
<string name="desc_sort">Desc</string> <string name="desc_sort">Desc</string>
<string name="login_start">Enter your credientials</string>
<string-array name="sort_criteria"> <string-array name="sort_criteria">
<item>alpha</item> <item>alpha</item>
<item>created</item> <item>created</item>
@ -24,4 +26,10 @@
<item>size</item> <item>size</item>
<item>id</item> <item>id</item>
</string-array> </string-array>
<string-array name="repository_tabs">
<item>Files</item>
<item>Issues</item>
<item>Pull requests</item>
<item>Releases</item>
</string-array>
</resources> </resources>
Loading…
Cancel
Save