List profil: swipe-kiri hapus (dengan konfirmasi), swipe-kanan edit

- ItemTouchHelper: swipe kiri -> dialog konfirmasi hapus profil (+kredensial)
- Swipe kanan -> buka ProfileEditorActivity untuk edit
- Item kembali ke posisi semula setelah swipe (hapus menunggu konfirmasi,
  edit pindah ke layar editor)
- ConnectActivity refactor: callback onEdit, helper openEditor(profileId)
This commit is contained in:
2026-08-30 23:27:44 +07:00
parent c0c6dab473
commit e9ded3d17a

View File

@@ -6,7 +6,9 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
@@ -29,16 +31,47 @@ class ConnectActivity : AppCompatActivity() {
setContentView(R.layout.activity_connect)
store = SecureStore(this)
adapter = ProfileAdapter { profile ->
val intent = Intent(this, TerminalActivity::class.java)
intent.putExtra("profile_id", profile.id)
startActivity(intent)
}
adapter = ProfileAdapter(
onOpen = { profile ->
val intent = Intent(this, TerminalActivity::class.java)
intent.putExtra("profile_id", profile.id)
startActivity(intent)
},
onEdit = { profile -> openEditor(profile.id) }
)
val list = findViewById<RecyclerView>(R.id.profileList)
list.layoutManager = LinearLayoutManager(this)
list.adapter = adapter
// Swipe: kiri = hapus, kanan = edit.
ItemTouchHelper(object : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int =
makeMovementFlags(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val pos = viewHolder.bindingAdapterPosition
val profile = adapter.itemAt(pos) ?: return
if (direction == ItemTouchHelper.LEFT) {
confirmDelete(profile)
} else {
openEditor(profile.id)
}
// Selalu kembalikan item ke tempatnya; hapus hanya setelah konfirmasi,
// edit hanya memindahkan ke layar editor.
adapter.notifyItemChanged(pos)
}
}).attachToRecyclerView(list)
findViewById<FloatingActionButton>(R.id.fabAdd).setOnClickListener {
editorLauncher.launch(Intent(this, ProfileEditorActivity::class.java))
}
@@ -51,6 +84,27 @@ class ConnectActivity : AppCompatActivity() {
refresh()
}
private fun openEditor(profileId: String) {
val intent = Intent(this, ProfileEditorActivity::class.java)
intent.putExtra("profile_id", profileId)
editorLauncher.launch(intent)
}
private fun confirmDelete(profile: ServerProfile) {
AlertDialog.Builder(this)
.setTitle("Hapus profil")
.setMessage(
"Hapus profil \"${profile.name}\" (${profile.host})?\n" +
"Kredensial tersimpan juga akan ikut terhapus."
)
.setPositiveButton("Hapus") { _, _ ->
store.deleteProfile(profile.id)
refresh()
}
.setNegativeButton("Batal", null)
.show()
}
private fun refresh() {
adapter.submit(store.getProfiles())
findViewById<TextView>(R.id.emptyHint).visibility =
@@ -59,7 +113,8 @@ class ConnectActivity : AppCompatActivity() {
}
private class ProfileAdapter(
private val onOpen: (ServerProfile) -> Unit
private val onOpen: (ServerProfile) -> Unit,
private val onEdit: (ServerProfile) -> Unit
) : RecyclerView.Adapter<ProfileAdapter.VH>() {
private var items: List<ServerProfile> = emptyList()
@@ -69,6 +124,9 @@ class ConnectActivity : AppCompatActivity() {
notifyDataSetChanged()
}
fun itemAt(position: Int): ServerProfile? =
if (position in items.indices) items[position] else null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.item_profile, parent, false)