List commits in a repository
This commit is contained in:
@@ -36,6 +36,9 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def nav_version = "2.5.3"
|
||||
def paging_version = "3.1.1"
|
||||
def fragment_version = "1.5.6"
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
@@ -45,8 +48,15 @@ dependencies {
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||
implementation 'com.squareup.moshi:moshi:1.14.0'
|
||||
implementation 'com.squareup.moshi:moshi-kotlin:1.14.0'
|
||||
implementation 'com.squareup.moshi:moshi-adapters:1.14.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||
implementation "androidx.paging:paging-runtime:$paging_version"
|
||||
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||
|
||||
//implementation 'androidx.core:core-ktx:+'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
|
@@ -3,12 +3,13 @@ package fr.uca.iut.clfreville2.teaiswarm
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.GiteaService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.max
|
||||
|
||||
const val REPOSITORY_OWNER = "repository_owner"
|
||||
const val REPOSITORY_NAME = "repository_name"
|
||||
@@ -17,18 +18,24 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
private val service = GiteaService()
|
||||
private lateinit var repositories: RecyclerView
|
||||
private lateinit var previousButton: Button
|
||||
private lateinit var nextButton: Button
|
||||
private var currentPage = 1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
repositories = findViewById(R.id.repositories_view)
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val repos = service.listActiveRepositories("clement.freville2", 1)
|
||||
lifecycleScope.launch {
|
||||
repositories.adapter = RepositoryListAdapter(repos) { repo ->
|
||||
adapterOnClick(repo)
|
||||
}
|
||||
}
|
||||
previousButton = findViewById(R.id.previous_repository_list)
|
||||
nextButton = findViewById(R.id.next_repository_list)
|
||||
updateList()
|
||||
previousButton.setOnClickListener {
|
||||
currentPage = max(currentPage - 1, 0)
|
||||
updateList()
|
||||
}
|
||||
nextButton.setOnClickListener {
|
||||
currentPage += 1
|
||||
updateList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +45,13 @@ class MainActivity : AppCompatActivity() {
|
||||
intent.putExtra(REPOSITORY_NAME, repository.name)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun updateList() {
|
||||
lifecycleScope.launch {
|
||||
val repos = service.listActiveRepositories("clement.freville2", currentPage)
|
||||
repositories.adapter = RepositoryListAdapter(repos) { repo ->
|
||||
adapterOnClick(repo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,45 +1,57 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
const val FILE_PATH = "file_path"
|
||||
|
||||
class RepositoryDetailActivity : AppCompatActivity() {
|
||||
|
||||
private val service = GiteaService()
|
||||
private lateinit var repositoryName: TextView
|
||||
private lateinit var versionedFiles: RecyclerView
|
||||
|
||||
private lateinit var currentRepositoryOwner: String
|
||||
private lateinit var currentRepositoryName: String
|
||||
private var currentFilePath: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_repository_detail)
|
||||
|
||||
repositoryName = findViewById(R.id.repository_detail_name)
|
||||
|
||||
var currentRepositoryOwner: String? = null
|
||||
var currentRepositoryName: String? = null
|
||||
val bundle: Bundle? = intent.extras
|
||||
if (bundle != null) {
|
||||
currentRepositoryOwner = bundle.getString(REPOSITORY_OWNER)
|
||||
currentRepositoryName = bundle.getString(REPOSITORY_NAME)
|
||||
currentRepositoryOwner = bundle.getString(REPOSITORY_OWNER)!!
|
||||
currentRepositoryName = bundle.getString(REPOSITORY_NAME)!!
|
||||
currentFilePath = bundle.getString(FILE_PATH)
|
||||
}
|
||||
|
||||
currentRepositoryName?.let {
|
||||
repositoryName.text = currentRepositoryName
|
||||
}
|
||||
repositoryName.text = currentRepositoryName
|
||||
|
||||
versionedFiles = findViewById(R.id.versioned_files_view)
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val repos = service.listFileContents(RepositoryIdentifier(currentRepositoryOwner!!, currentRepositoryName!!), "")
|
||||
lifecycleScope.launch {
|
||||
versionedFiles.adapter = FileListAdapter(repos) {}
|
||||
lifecycleScope.launch {
|
||||
val repos = service.listFileContents(RepositoryIdentifier(currentRepositoryOwner, currentRepositoryName), currentFilePath ?: "")
|
||||
versionedFiles.adapter = FileListAdapter(repos) {
|
||||
file -> adapterOnClick(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun adapterOnClick(file: VersionedFile) {
|
||||
val intent = Intent(this, RepositoryDetailActivity()::class.java)
|
||||
intent.putExtra(REPOSITORY_OWNER, currentRepositoryOwner)
|
||||
intent.putExtra(REPOSITORY_NAME, currentRepositoryName)
|
||||
intent.putExtra(FILE_PATH, (currentFilePath ?: "") + file.name)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,149 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.paging.*
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
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
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class ActivityListFragment : Fragment(R.layout.activity_list) {
|
||||
|
||||
private val service = GiteaService()
|
||||
var repository: RepositoryIdentifier? = null
|
||||
var sha: String? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateCommits()
|
||||
}
|
||||
|
||||
private fun updateCommits() {
|
||||
val viewModel by viewModels<ActivityViewModel>(
|
||||
factoryProducer = {
|
||||
ActivityViewModelFactory(
|
||||
service,
|
||||
repository!!,
|
||||
sha
|
||||
)
|
||||
}
|
||||
)
|
||||
val pagingAdapter = ActivityAdapter(ActivityComparator)
|
||||
val recyclerView = requireView().findViewById<RecyclerView>(R.id.activity_list_view)
|
||||
recyclerView.adapter = pagingAdapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.flow.collectLatest { pagingData ->
|
||||
pagingAdapter.submitData(pagingData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ActivitySource(
|
||||
private val service: RepositoryService,
|
||||
private val repository: RepositoryIdentifier,
|
||||
private val sha: String?
|
||||
) : PagingSource<Int, CommitActivity>() {
|
||||
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CommitActivity> =
|
||||
try {
|
||||
val nextPageNumber = params.key ?: 1
|
||||
val response = service.listCommits(repository, sha, nextPageNumber)
|
||||
LoadResult.Page(
|
||||
data = response,
|
||||
prevKey = nextPageNumber - 1,
|
||||
nextKey = nextPageNumber + 1
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
LoadResult.Error(e)
|
||||
} catch (e: HttpException) {
|
||||
LoadResult.Error(e)
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, CommitActivity>): Int? =
|
||||
state.anchorPosition?.let { anchorPosition ->
|
||||
val anchorPage = state.closestPageToPosition(anchorPosition)
|
||||
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
|
||||
}
|
||||
}
|
||||
|
||||
class ActivityAdapter(diffCallback: DiffUtil.ItemCallback<CommitActivity>) :
|
||||
PagingDataAdapter<CommitActivity, ViewHolder>(diffCallback) {
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.activity_row_item, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) =
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
private val commitNameView: TextView
|
||||
|
||||
init {
|
||||
commitNameView = view.findViewById(R.id.commit_name)
|
||||
}
|
||||
|
||||
fun bind(commit: CommitActivity?) {
|
||||
commit?.let {
|
||||
commitNameView.text = it.commit.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ActivityComparator : DiffUtil.ItemCallback<CommitActivity>() {
|
||||
override fun areItemsTheSame(oldItem: CommitActivity, newItem: CommitActivity): Boolean =
|
||||
oldItem.sha == newItem.sha
|
||||
|
||||
override fun areContentsTheSame(oldItem: CommitActivity, newItem: CommitActivity): Boolean =
|
||||
oldItem == newItem
|
||||
}
|
||||
|
||||
class ActivityViewModel(
|
||||
private val service: RepositoryService,
|
||||
private val repository: RepositoryIdentifier,
|
||||
private val sha: String?
|
||||
) : ViewModel() {
|
||||
val flow = Pager(
|
||||
PagingConfig(pageSize = 10, enablePlaceholders = true)
|
||||
) {
|
||||
ActivitySource(service, repository, sha)
|
||||
}.flow
|
||||
}
|
||||
|
||||
class ActivityViewModelFactory(
|
||||
private val service: RepositoryService,
|
||||
private val repository: RepositoryIdentifier,
|
||||
private val sha: String?
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(ActivityViewModel::class.java)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return ActivityViewModel(service, repository, sha) as T
|
||||
}
|
||||
throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
import java.util.Date
|
||||
|
||||
data class Author(val name: String, val email: String, val date: Date)
|
@@ -0,0 +1,3 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
data class CommitActivity(val sha: String, val commit: Commit, val author: Owner?, val committer: Owner?)
|
@@ -0,0 +1,14 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
|
||||
enum class FileType {
|
||||
@Json(name = "file")
|
||||
FILE,
|
||||
@Json(name = "dir")
|
||||
DIR,
|
||||
@Json(name = "symlink")
|
||||
SYMLINK,
|
||||
@Json(name = "submodule")
|
||||
SUBMODULE
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
data class Commit(val author: Author, val committer: Author, val message: String)
|
@@ -0,0 +1,3 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
data class Verification(val verified: Boolean)
|
@@ -1,3 +1,3 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.model
|
||||
|
||||
data class VersionedFile(val name: String)
|
||||
data class VersionedFile(val name: String, val type: FileType)
|
||||
|
@@ -1,23 +1,29 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.network
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapters.EnumJsonAdapter
|
||||
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.Repository
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifiable
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.VersionedFile
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import java.util.*
|
||||
|
||||
interface GiteaApiService {
|
||||
|
||||
@GET("users/{username}/repos")
|
||||
suspend fun listActiveRepositories(@Path("username") username: String, @Query("page") page: Int): List<Repository>
|
||||
|
||||
@GET("repos/{owner}/{repo}/commits")
|
||||
suspend fun listCommits(@Path("owner") owner: String, @Path("repo") repo: String, @Query("sha") sha: String?, @Query("page") page: Int): List<CommitActivity>
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents/{filePath}")
|
||||
suspend fun listFileContents(@Path("owner") owner: String, @Path("repo") repo: String, @Path("filePath") filePath: String): List<VersionedFile>
|
||||
}
|
||||
@@ -26,11 +32,21 @@ class GiteaService(private val handle: GiteaApiService) : RepositoryService {
|
||||
|
||||
constructor() : this(createRetrofit().create(GiteaApiService::class.java))
|
||||
|
||||
override suspend fun listActiveRepositories(username: String, page: Int): List<Repository> =
|
||||
override suspend fun listActiveRepositories(username: String, page: Int): List<Repository> = withContext(Dispatchers.IO) {
|
||||
handle.listActiveRepositories(username, page)
|
||||
}
|
||||
|
||||
override suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List<VersionedFile> =
|
||||
override suspend fun listCommits(
|
||||
repository: RepositoryIdentifiable,
|
||||
sha: String?,
|
||||
page: Int
|
||||
): List<CommitActivity> = withContext(Dispatchers.IO) {
|
||||
handle.listCommits(repository.identifier.owner, repository.identifier.name, sha, page)
|
||||
}
|
||||
|
||||
override suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List<VersionedFile> = withContext(Dispatchers.IO) {
|
||||
handle.listFileContents(repository.identifier.owner, repository.identifier.name, filePath)
|
||||
}
|
||||
}
|
||||
|
||||
private const val CODEFIRST_API_BASE = "https://codefirst.iut.uca.fr/git/api/v1/"
|
||||
@@ -42,6 +58,7 @@ private fun createRetrofit(): Retrofit =
|
||||
.baseUrl(CODEFIRST_API_BASE)
|
||||
.addConverterFactory(MoshiConverterFactory.create(
|
||||
Moshi.Builder()
|
||||
.add(Date::class.java, Rfc3339DateJsonAdapter().nullSafe())
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()))
|
||||
.client(httpClient)
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.network
|
||||
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifiable
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.VersionedFile
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.*
|
||||
|
||||
interface RepositoryService {
|
||||
|
||||
suspend fun listActiveRepositories(username: String, page: Int): List<Repository>
|
||||
|
||||
suspend fun listCommits(repository: RepositoryIdentifiable, sha: String?, page: Int): List<CommitActivity>
|
||||
|
||||
suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String): List<VersionedFile>
|
||||
}
|
||||
|
@@ -1,9 +1,8 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.network
|
||||
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Owner
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.Repository
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifiable
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.VersionedFile
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.*
|
||||
import java.util.Date
|
||||
import kotlin.random.Random
|
||||
|
||||
class StubRepositoryService : RepositoryService {
|
||||
|
||||
@@ -28,6 +27,22 @@ class StubRepositoryService : RepositoryService {
|
||||
else -> listOf()
|
||||
}.map { Repository(Owner(-1, ""), it) }
|
||||
|
||||
override suspend fun listCommits(
|
||||
repository: RepositoryIdentifiable,
|
||||
sha: String?,
|
||||
page: Int
|
||||
): List<CommitActivity> {
|
||||
val author = Author("clement.freville2", "clement.freville2@etu.uca.fr", Date())
|
||||
return (0..10).map {
|
||||
CommitActivity(
|
||||
randomCommitSha(),
|
||||
Commit(author, author, "Implement parser"),
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun listFileContents(repository: RepositoryIdentifiable, filePath: String) =
|
||||
listOf(
|
||||
"cli",
|
||||
@@ -39,5 +54,10 @@ class StubRepositoryService : RepositoryService {
|
||||
".gitignore",
|
||||
"CONVENTIONS.md",
|
||||
"README.md"
|
||||
).map { VersionedFile(it) }
|
||||
).map { VersionedFile(it, if (it.contains(".")) { FileType.FILE } else { FileType.DIR }) }
|
||||
}
|
||||
|
||||
val CHAR_POOL = "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
|
||||
fun randomCommitSha() = (1..40)
|
||||
.map { Random.nextInt(0, CHAR_POOL.size).let { CHAR_POOL[it] } }
|
||||
.joinToString("")
|
||||
|
9
app/src/main/res/layout/activity_list.xml
Normal file
9
app/src/main/res/layout/activity_list.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/activity_list_view" />
|
||||
</FrameLayout>
|
@@ -12,4 +12,21 @@
|
||||
android:layout_height="match_parent"
|
||||
app:layoutManager="LinearLayoutManager"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/previous_repository_list"
|
||||
android:text="@string/previous" />
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/next_repository_list"
|
||||
android:text="@string/next" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
9
app/src/main/res/layout/activity_row_item.xml
Normal file
9
app/src/main/res/layout/activity_row_item.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?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:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/commit_name" />
|
||||
</LinearLayout>
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
@@ -8,4 +8,4 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/repository_name" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
@@ -2,4 +2,10 @@
|
||||
<string name="app_name">TeaIsWarm</string>
|
||||
<string name="repository_name">Repository name</string>
|
||||
<string name="repository_description">Repository description</string>
|
||||
<plurals name="stars">
|
||||
<item quantity="one">%d star</item>
|
||||
<item quantity="other">%d stars</item>
|
||||
</plurals>
|
||||
<string name="previous">Previous</string>
|
||||
<string name="next">Next</string>
|
||||
</resources>
|
Reference in New Issue
Block a user