Add drag to re-arrange support for quick chat actions

This commit is contained in:
Douile
2022-08-12 15:35:27 +01:00
parent 7da224a1ce
commit 1bdb6bf340
8 changed files with 92 additions and 14 deletions

View File

@@ -24,11 +24,15 @@ class QuickChatActionRepository @Inject constructor(private val quickChatDaoLazy
quickChatActionDao.deleteAll()
}
suspend fun delete(uuid: Long) = withContext(Dispatchers.IO) {
quickChatActionDao.delete(uuid)
suspend fun delete(action: QuickChatAction) = withContext(Dispatchers.IO) {
quickChatActionDao.delete(action)
}
suspend fun update(action:QuickChatAction) = withContext(Dispatchers.IO) {
suspend fun update(action: QuickChatAction) = withContext(Dispatchers.IO) {
quickChatActionDao.update(action)
}
suspend fun moveAction(action: QuickChatAction, newPos: Int) = withContext(Dispatchers.IO) {
quickChatActionDao.moveAction(action, newPos)
}
}

View File

@@ -1,9 +1,6 @@
package com.geeksville.mesh.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import androidx.room.*
import com.geeksville.mesh.database.entity.QuickChatAction
import kotlinx.coroutines.flow.Flow
@@ -20,9 +17,41 @@ interface QuickChatActionDao {
fun deleteAll()
@Query("Delete from quick_chat where uuid=:uuid")
fun delete(uuid: Long)
fun _delete(uuid: Long)
@Transaction
fun delete(action: QuickChatAction) {
_delete(action.uuid)
decrementPositionsAfter(action.position)
}
@Update
fun update(action: QuickChatAction)
@Query("Update quick_chat set position=:position WHERE uuid=:uuid")
fun updateActionPosition(uuid: Long, position: Int)
@Query("Update quick_chat set position=position+1 where position>=:startInclusive and position<:endExclusive")
fun incrementPositionsBetween(startInclusive: Int, endExclusive: Int)
@Query("Update quick_chat SET position=position-1 where position>:startExclusive and position<=:endInclusive")
fun decrementPositionsBetween(startExclusive: Int, endInclusive: Int)
@Query("Update quick_chat set position=position-1 where position>=:position")
fun decrementPositionsAfter(position: Int)
@Transaction
fun moveAction(action: QuickChatAction, newPos: Int) {
// FIXME: Check newPos is valid
if (newPos < action.position) {
incrementPositionsBetween(newPos, action.position)
updateActionPosition(action.uuid, newPos)
} else if (newPos > action.position) {
decrementPositionsBetween(action.position, newPos)
updateActionPosition(action.uuid, newPos)
} else {
// Do nothing: moving to same position
}
}
}

View File

@@ -2,14 +2,16 @@ package com.geeksville.mesh.database.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = "quick_chat")
@Entity(tableName = "quick_chat", indices = [Index(value=["position"], unique=true)])
data class QuickChatAction(
@PrimaryKey(autoGenerate = true) val uuid: Long,
@ColumnInfo(name="name") val name: String,
@ColumnInfo(name="message") val message: String,
@ColumnInfo(name="mode") val mode: Mode) {
@ColumnInfo(name="mode") val mode: Mode,
@ColumnInfo(name="position") val position: Int) {
enum class Mode {
Append,
Instant,

View File

@@ -461,14 +461,14 @@ class UIViewModel @Inject constructor(
fun addQuickChatAction(name: String, value: String, mode: QuickChatAction.Mode) {
viewModelScope.launch(Dispatchers.Main) {
val action = QuickChatAction(0, name, value, mode)
val action = QuickChatAction(0, name, value, mode, _quickChatActions.value.size)
quickChatActionRepository.insert(action)
}
}
fun deleteQuickChatAction(action: QuickChatAction) {
viewModelScope.launch(Dispatchers.Main) {
quickChatActionRepository.delete(action.uuid)
quickChatActionRepository.delete(action)
}
}
@@ -483,10 +483,17 @@ class UIViewModel @Inject constructor(
action.uuid,
name ?: action.name,
message ?: action.message,
mode ?: action.mode
mode ?: action.mode,
action.position
)
quickChatActionRepository.update(newAction)
}
}
fun moveQuickChatAction(action: QuickChatAction, newPos: Int) {
viewModelScope.launch(Dispatchers.Main) {
quickChatActionRepository.moveAction(action, newPos)
}
}
}

View File

@@ -0,0 +1,24 @@
package com.geeksville.mesh.ui
import android.content.Context
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
class DragManageAdapter(var adapter: SwapAdapter, context: Context, dragDirs: Int, swipeDirs: Int) : ItemTouchHelper.SimpleCallback(dragDirs, swipeDirs) {
interface SwapAdapter {
fun swapItems(fromPosition: Int, toPosition: Int)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
adapter.swapItems(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
TODO("Not yet implemented")
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
TODO("Not yet implemented")
}
}

View File

@@ -307,6 +307,7 @@ class MessagesFragment : Fragment(), Logging {
model.quickChatActions.asLiveData().observe(viewLifecycleOwner) { actions ->
actions?.let {
binding.quickChatLayout.removeAllViews()
for (action in actions) {
val button = Button(context)
button.setText(action.name)

View File

@@ -13,7 +13,7 @@ import com.geeksville.mesh.database.entity.QuickChatAction
class QuickChatActionAdapter internal constructor(
context: Context,
private val onEdit: (action: QuickChatAction) -> Unit
) : RecyclerView.Adapter<QuickChatActionAdapter.ActionViewHolder>() {
) : RecyclerView.Adapter<QuickChatActionAdapter.ActionViewHolder>(), DragManageAdapter.SwapAdapter {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var actions = emptyList<QuickChatAction>()
@@ -50,4 +50,9 @@ class QuickChatActionAdapter internal constructor(
override fun getItemCount() = actions.size
override fun swapItems(fromPosition: Int, toPosition: Int) {
// TODO: Update data
notifyItemMoved(fromPosition, toPosition)
}
}

View File

@@ -9,6 +9,7 @@ import android.widget.EditText
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.asLiveData
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.geeksville.android.Logging
import com.geeksville.mesh.R
@@ -84,11 +85,16 @@ class QuickChatSettingsFragment : ScreenFragment("Quick Chat settings"), Logging
dialog.show()
}
val dragCallback = DragManageAdapter(quickChatActionAdapter, requireContext(), ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0)
val helper = ItemTouchHelper(dragCallback)
binding.quickChatSettingsView.apply {
this.layoutManager = LinearLayoutManager(requireContext())
this.adapter = quickChatActionAdapter
helper.attachToRecyclerView(this)
}
model.quickChatActions.asLiveData().observe(viewLifecycleOwner) { actions ->
actions?.let { quickChatActionAdapter.setActions(actions) }
}