Add comment support
This commit is contained in:
@@ -3,6 +3,8 @@ plugins {
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
namespace 'fr.uca.iut.clfreville2.teaiswarm'
|
||||
compileSdk 33
|
||||
@@ -10,7 +12,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "fr.uca.iut.clfreville2.teaiswarm"
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
@@ -40,8 +42,9 @@ dependencies {
|
||||
def paging_version = "3.1.1"
|
||||
def fragment_version = "1.5.6"
|
||||
def preference_version = "1.2.0"
|
||||
def room_version = "2.5.1"
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.core:core-ktx:1.10.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.8.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
@@ -60,7 +63,10 @@ dependencies {
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'io.coil-kt:coil:2.3.0'
|
||||
|
||||
//implementation 'androidx.core:core-ktx:+'
|
||||
implementation "androidx.room:room-ktx:$room_version"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
|
@@ -14,6 +14,7 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.TeaIsWarm"
|
||||
android:name=".TeaIsWarm"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
@@ -1,10 +1,15 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm
|
||||
|
||||
import android.app.Application
|
||||
import fr.uca.iut.clfreville2.teaiswarm.db.TeaDatabase
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.GiteaService
|
||||
import fr.uca.iut.clfreville2.teaiswarm.network.RepositoryService
|
||||
|
||||
object TeaIsWarm {
|
||||
class TeaIsWarm : Application() {
|
||||
|
||||
val database: TeaDatabase by lazy {
|
||||
TeaDatabase.getInstance(this)
|
||||
}
|
||||
val service: RepositoryService by lazy {
|
||||
GiteaService()
|
||||
}
|
||||
|
@@ -0,0 +1,71 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
import fr.uca.iut.clfreville2.teaiswarm.db.CommentDao
|
||||
import fr.uca.iut.clfreville2.teaiswarm.db.CommentEntity
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
|
||||
|
||||
class CommentListAdapter : ListAdapter<CommentEntity, CommentListAdapter.CommentViewHolder>(CommentComparator) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommentViewHolder {
|
||||
val view: View = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.comment_view_item, parent, false)
|
||||
return CommentViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CommentViewHolder, position: Int) {
|
||||
val current = getItem(position)
|
||||
holder.bind(current.comment)
|
||||
}
|
||||
|
||||
class CommentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val commentText: EditText = itemView.findViewById(R.id.comment_edit_text)
|
||||
|
||||
fun bind(text: String?) {
|
||||
commentText.setText(text)
|
||||
}
|
||||
}
|
||||
|
||||
object CommentComparator : DiffUtil.ItemCallback<CommentEntity>() {
|
||||
override fun areItemsTheSame(oldItem: CommentEntity, newItem: CommentEntity): Boolean {
|
||||
return oldItem === newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: CommentEntity, newItem: CommentEntity): Boolean {
|
||||
return oldItem.comment == newItem.comment
|
||||
}
|
||||
}
|
||||
|
||||
class CommentViewModel(
|
||||
repository: RepositoryIdentifier,
|
||||
commentDao: CommentDao
|
||||
) : ViewModel() {
|
||||
val allItems: LiveData<List<CommentEntity>> =
|
||||
commentDao.getForRepository(repository.owner, repository.name).asLiveData()
|
||||
}
|
||||
|
||||
class CommentViewModelFactory(
|
||||
private val repository: RepositoryIdentifier,
|
||||
private val commentDao: CommentDao
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(CommentViewModel::class.java)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return CommentViewModel(repository, commentDao) as T
|
||||
}
|
||||
throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +1,11 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm
|
||||
package fr.uca.iut.clfreville2.teaiswarm.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import fr.uca.iut.clfreville2.teaiswarm.R
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.VersionedFile
|
||||
|
||||
class FileListAdapter(private val dataSet: List<VersionedFile>, private val onClick: (VersionedFile) -> Unit) :
|
@@ -0,0 +1,20 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.db
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CommentDao {
|
||||
|
||||
@Insert
|
||||
fun insert(comment: CommentEntity)
|
||||
|
||||
@Update
|
||||
fun update(comment: CommentEntity)
|
||||
|
||||
@Delete
|
||||
fun delete(comment: CommentEntity)
|
||||
|
||||
@Query("SELECT * FROM comment WHERE owner = :owner AND repository = :repository")
|
||||
fun getForRepository(owner: String, repository: String): Flow<List<CommentEntity>>
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.db
|
||||
|
||||
import androidx.room.Entity
|
||||
|
||||
@Entity(tableName = "comment", primaryKeys = ["id"])
|
||||
data class CommentEntity(val id: Int? = null, val owner: String, val repository: String, val comment: String)
|
@@ -0,0 +1,26 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(entities = [CommentEntity::class], version = 1, exportSchema = false)
|
||||
abstract class TeaDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun commentDao(): CommentDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: TeaDatabase? = null
|
||||
|
||||
fun getInstance(ctx: Context): TeaDatabase =
|
||||
instance ?: synchronized(this) {
|
||||
Room.databaseBuilder(
|
||||
ctx.applicationContext,
|
||||
TeaDatabase::class.java,
|
||||
"tea.db"
|
||||
).build().also { instance = it }
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,7 +31,7 @@ import java.io.IOException
|
||||
|
||||
class ActivityListFragment : Fragment(R.layout.activity_list) {
|
||||
|
||||
private val service = TeaIsWarm.service
|
||||
private lateinit var service: RepositoryService
|
||||
var repository: RepositoryIdentifier? = null
|
||||
var sha: String? = null
|
||||
|
||||
@@ -39,6 +39,7 @@ class ActivityListFragment : Fragment(R.layout.activity_list) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
service = (activity?.application as TeaIsWarm).service
|
||||
if (view is SwipeRefreshLayout) {
|
||||
view.setOnRefreshListener {
|
||||
updateCommits()
|
||||
|
@@ -18,7 +18,7 @@ class CodeViewFragment : Fragment(R.layout.code_view_fragment) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val service = TeaIsWarm.service
|
||||
val service = (activity?.application as TeaIsWarm).service
|
||||
val bundle = requireArguments()
|
||||
val repository = RepositoryIdentifier(
|
||||
bundle.getString(REPOSITORY_OWNER)!!,
|
||||
|
@@ -0,0 +1,55 @@
|
||||
package fr.uca.iut.clfreville2.teaiswarm.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
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.adapter.CommentListAdapter
|
||||
import fr.uca.iut.clfreville2.teaiswarm.db.CommentEntity
|
||||
import fr.uca.iut.clfreville2.teaiswarm.model.RepositoryIdentifier
|
||||
|
||||
class CommentListFragment : Fragment() {
|
||||
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val owner = arguments?.getString(REPOSITORY_OWNER)!!
|
||||
val repo = arguments?.getString(REPOSITORY_NAME)!!
|
||||
val repository = RepositoryIdentifier(owner, repo)
|
||||
val viewModel: CommentListAdapter.CommentViewModel by activityViewModels {
|
||||
CommentListAdapter.CommentViewModelFactory(
|
||||
repository,
|
||||
(activity?.application as TeaIsWarm).database.commentDao()
|
||||
)
|
||||
}
|
||||
|
||||
(activity?.application as TeaIsWarm).database.commentDao().insert(
|
||||
CommentEntity(
|
||||
null,
|
||||
owner,
|
||||
repo,
|
||||
"test"
|
||||
)
|
||||
)
|
||||
|
||||
recyclerView = view.findViewById(R.id.comment_list)
|
||||
|
||||
val adapter = CommentListAdapter()
|
||||
recyclerView.adapter = adapter
|
||||
viewModel.allItems.observe(this.viewLifecycleOwner) { items ->
|
||||
items.let {
|
||||
adapter.submitList(it)
|
||||
}
|
||||
}
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
|
||||
}
|
@@ -6,14 +6,18 @@ import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.add
|
||||
import androidx.fragment.app.commit
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import fr.uca.iut.clfreville2.teaiswarm.*
|
||||
import fr.uca.iut.clfreville2.teaiswarm.adapter.FileListAdapter
|
||||
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.RepositoryService
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.io.path.Path
|
||||
|
||||
@@ -21,13 +25,13 @@ const val FILE_PATH = "file_path"
|
||||
|
||||
class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
|
||||
private val service = TeaIsWarm.service
|
||||
private lateinit var service: RepositoryService
|
||||
private lateinit var repositoryOwner: TextView
|
||||
private lateinit var repositoryName: TextView
|
||||
private lateinit var repositoryDescription: TextView
|
||||
private lateinit var repositoryStars: TextView
|
||||
private lateinit var repositoryForks: TextView
|
||||
private lateinit var activity: Button
|
||||
private lateinit var activityButton: Button
|
||||
private lateinit var versionedFiles: RecyclerView
|
||||
|
||||
private lateinit var currentRepositoryOwner: String
|
||||
@@ -36,12 +40,13 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
service = (activity?.application as TeaIsWarm).service
|
||||
repositoryOwner = view.findViewById(R.id.repository_detail_owner)
|
||||
repositoryName = view.findViewById(R.id.repository_detail_name)
|
||||
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)
|
||||
activityButton = view.findViewById(R.id.repository_detail_activity)
|
||||
|
||||
val bundle = requireArguments()
|
||||
currentRepositoryOwner = bundle.getString(REPOSITORY_OWNER)!!
|
||||
@@ -67,7 +72,7 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
}
|
||||
}
|
||||
|
||||
activity.setOnClickListener {
|
||||
activityButton.setOnClickListener {
|
||||
findNavController().navigate(R.id.activity_list_fragment, bundle)
|
||||
}
|
||||
|
||||
@@ -75,6 +80,16 @@ class RepositoryDetailsFragment : Fragment(R.layout.repository_details) {
|
||||
resources.getStringArray(R.array.repository_tabs).forEach {
|
||||
tabLayout.addTab(tabLayout.newTab().setText(it))
|
||||
}
|
||||
|
||||
parentFragmentManager.commit {
|
||||
setReorderingAllowed(true)
|
||||
add<CommentListFragment>(
|
||||
R.id.comment_fragment_container, args = bundleOf(
|
||||
REPOSITORY_OWNER to currentRepositoryOwner,
|
||||
REPOSITORY_NAME to currentRepositoryName
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun adapterOnClick(file: VersionedFile) {
|
||||
|
@@ -35,7 +35,7 @@ class RepositoryListFragment(
|
||||
private val onClick: (Repository) -> Unit
|
||||
) : Fragment(R.layout.repository_list) {
|
||||
|
||||
private val service = TeaIsWarm.service
|
||||
private lateinit var service: RepositoryService
|
||||
private var lateInit = true
|
||||
private var search: SearchSettings by Delegates.observable(initialSearch) { _, _, _ ->
|
||||
if (!lateInit) {
|
||||
@@ -54,6 +54,7 @@ class RepositoryListFragment(
|
||||
view.isRefreshing = false
|
||||
}
|
||||
}
|
||||
service = (activity?.application as TeaIsWarm).service
|
||||
recyclerView = view.findViewById(R.id.repositories_view)
|
||||
val spinner: Spinner = view.findViewById(R.id.sort_by_spinner)
|
||||
ArrayAdapter.createFromResource(
|
||||
|
@@ -25,10 +25,11 @@ class SetupConfigFragment(private val preferences: SharedPreferences) : Fragment
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
usernameInput = view.findViewById(R.id.username_input)
|
||||
confirmButton = view.findViewById(R.id.configure_button)
|
||||
val service = (activity?.application as TeaIsWarm).service
|
||||
confirmButton.setOnClickListener {
|
||||
val username = usernameInput.text.toString()
|
||||
lifecycleScope.launch {
|
||||
val owner = TeaIsWarm.service.searchOwner(username)
|
||||
val owner = service.searchOwner(username)
|
||||
if (owner is Owner) {
|
||||
preferences.edit {
|
||||
putString(USERNAME, usernameInput.text.toString())
|
||||
|
9
app/src/main/res/layout/comment_list_fragment.xml
Normal file
9
app/src/main/res/layout/comment_list_fragment.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">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/comment_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
12
app/src/main/res/layout/comment_view_item.xml
Normal file
12
app/src/main/res/layout/comment_view_item.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?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">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/comment_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:inputType="text|textMultiLine" />
|
||||
|
||||
</LinearLayout>
|
@@ -120,4 +120,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutManager="LinearLayoutManager"/>
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/comment_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
|
@@ -2,5 +2,5 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.3.0' apply false
|
||||
id 'com.android.library' version '7.3.0' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.8.20-RC' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
|
||||
}
|
Reference in New Issue
Block a user