From 133f45fc7b49a65a5d56017791c5cd81620d40aa Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 13 Mar 2025 10:19:47 +0100 Subject: [PATCH] supression projet --- .../com/dreamteam/timelapse/ProjectAdapter.kt | 42 ++++++++++++++- .../com/dreamteam/timelapse/ProjetsFrag.kt | 51 ++++++++++++++++++- .../dreamteam/timelapse/data/ApiService.kt | 3 ++ .../timelapse/data/ProjectRepository.kt | 17 +++++++ app/src/main/res/drawable/ic_delete.xml | 11 ++++ app/src/main/res/layout/item_project_card.xml | 5 ++ 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/drawable/ic_delete.xml diff --git a/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt b/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt index c35d666..b0db57b 100644 --- a/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt +++ b/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt @@ -1,5 +1,6 @@ package com.dreamteam.timelapse +import android.content.Context import android.content.Intent import android.util.Log import android.view.LayoutInflater @@ -7,14 +8,28 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView +import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide +import com.dreamteam.timelapse.data.ApiService import com.dreamteam.timelapse.data.Project +import com.dreamteam.timelapse.data.ProjectRepository +import com.google.android.material.snackbar.Snackbar +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory -class ProjectAdapter(private val projects: List, private val listener: OnEmptyStateListener) : RecyclerView.Adapter() { +class ProjectAdapter(private val projects: MutableList, private val listener: OnEmptyStateListener) : RecyclerView.Adapter() { + val projectRepository : ProjectRepository; init{ + val retrofit = Retrofit.Builder() + .baseUrl("https://timelapse.kerboul.me/api/") + .addConverterFactory(GsonConverterFactory.create()) + .build() + + projectRepository = ProjectRepository(retrofit.create(ApiService::class.java)) listener.onEmptyStateChanged(projects.isEmpty()) } @@ -57,7 +72,32 @@ class ProjectAdapter(private val projects: List, private val listener: context.startActivity(intent) } } + fun removeItem(position: Int, context: Context, v : View) { + val builder = AlertDialog.Builder(context) + val dialog = builder.setTitle("Confirm Deletion") + .setMessage("Voulez vous supprimer ce projet ?") + .setPositiveButton("Supprimer") { dialog, _ -> + projectRepository.deleteProject(projects[position].id, onSuccess = { + val name = projects[position].name + projects.removeAt(position) + notifyItemRemoved(position) + Snackbar.make(v.rootView, "$name supprimé avec succès !", Snackbar.LENGTH_SHORT).show() + }, onError = {s -> + dialog.dismiss() + notifyItemChanged(position) + Snackbar.make(v.rootView, "Error while trying to delete ${projects[position].name} : $s", Snackbar.LENGTH_SHORT).show() + }) + } + .setNegativeButton("Annuler") { dialog, _ -> + dialog.dismiss() + notifyItemChanged(position) // Reset swipe animation + } + .show() + dialog.setOnDismissListener { + notifyItemChanged(position) // Ensure the card resets when dialog closes + } + } override fun getItemCount(): Int { return projects.size } diff --git a/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt b/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt index 06c9039..62debd7 100644 --- a/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt +++ b/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt @@ -1,5 +1,8 @@ package com.dreamteam.timelapse +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.util.Log import android.util.TypedValue @@ -8,7 +11,9 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.GridLayout +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.dreamteam.timelapse.data.ProjectRepository @@ -72,6 +77,48 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener { recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(context) + val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) { + private val background = ColorDrawable(Color.RED) // Red background + private val deleteIcon = context?.let { ContextCompat.getDrawable(it, R.drawable.ic_delete) } + override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { + return false + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + val position = viewHolder.adapterPosition + context?.let { (recyclerView.adapter as ProjectAdapter).removeItem(position, it, viewHolder.itemView) } + } + override fun onChildDraw( + c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, + dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean + ) { + val itemView = viewHolder.itemView + val backgroundCornerOffset = 20 // Slight offset for smooth animation + + background.setBounds( + itemView.left, + itemView.top, + itemView.left + dX.toInt() - backgroundCornerOffset, + itemView.bottom + ) + //background.draw(c) + + // Position the delete icon + val iconMargin = (itemView.height - deleteIcon!!.intrinsicHeight) / 2 + val iconRight = itemView.left + iconMargin + deleteIcon.intrinsicWidth + val iconLeft = itemView.left + iconMargin + val iconTop = itemView.top + (itemView.height - deleteIcon.intrinsicHeight) / 2 + val iconBottom = iconTop + deleteIcon.intrinsicHeight + + deleteIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom) + deleteIcon.draw(c) + + + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + } + }) + + itemTouchHelper.attachToRecyclerView(recyclerView) } private fun fetchProjects() { @@ -86,7 +133,7 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener { onSuccess = { projects -> Log.d("ProjetsFrag", "Projets reçus : $projects") this.projects = projects - this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir) + this.projectAdapter = ProjectAdapter(this.projects.toMutableList(), this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir) this.recyclerView.adapter = this.projectAdapter // Mettre à jour le RecyclerView ou autre traitement }, @@ -94,7 +141,7 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener { Log.e("ProjetsFrag prout", errorMessage) //onEmptyStateChanged(true) this.projects = listOf() - this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir) + this.projectAdapter = ProjectAdapter(this.projects.toMutableList(), this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir) this.recyclerView.adapter = this.projectAdapter } diff --git a/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt b/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt index 401fbca..fc68c25 100644 --- a/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt +++ b/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt @@ -1,6 +1,7 @@ package com.dreamteam.timelapse.data import retrofit2.Call import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.Field import retrofit2.http.FormUrlEncoded import retrofit2.http.GET @@ -20,4 +21,6 @@ interface ApiService { fun createProject(@Body project: Project): Call @GET("projects/{id}/videos") fun getVideosOfProject(@Path("id") projectId:Int): Call> + @DELETE("projects/{id}") + fun deleteProject(@Path("id") projectId:Int) : Call } \ No newline at end of file diff --git a/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt b/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt index eeb431e..e4cacd2 100644 --- a/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt +++ b/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt @@ -82,4 +82,21 @@ class ProjectRepository(private val apiService: ApiService) { }) } + fun deleteProject(id : Int, onSuccess: ()->Unit, onError: (String) -> Unit){ + val call = apiService.deleteProject(id) + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + onSuccess() + } else { + onError("Erreur : ${response.code()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + onError("Échec de l'appel API : ${t.message}") + } + }) + } + } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000..7136c3a --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/layout/item_project_card.xml b/app/src/main/res/layout/item_project_card.xml index 1bd2e3e..ec4a5de 100644 --- a/app/src/main/res/layout/item_project_card.xml +++ b/app/src/main/res/layout/item_project_card.xml @@ -22,6 +22,10 @@ android:clipChildren="false" android:clipToPadding="false"> + +