Use list adapter for checklists

This commit is contained in:
Naveen Singh
2024-07-20 00:30:30 +05:30
parent 9fed832001
commit 57f8f667b6
8 changed files with 96 additions and 90 deletions

View File

@@ -171,10 +171,12 @@ class WidgetConfigureActivity : SimpleActivity() {
}
}
ChecklistAdapter(this, items, null, binding.checklistNoteView, false) {}.apply {
ChecklistAdapter(this, null, binding.checklistNoteView).apply {
updateTextColor(mTextColor)
binding.checklistNoteView.adapter = this
submitList(items.toList())
}
binding.textNoteView.beGone()
binding.checklistNoteView.beVisible()
} else {

View File

@@ -7,10 +7,12 @@ import android.view.Menu
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.adapters.MyRecyclerViewAdapter
import org.fossify.commons.adapters.MyRecyclerViewListAdapter
import org.fossify.commons.extensions.applyColorFilter
import org.fossify.commons.extensions.beVisibleIf
import org.fossify.commons.extensions.removeBit
@@ -31,18 +33,19 @@ import java.util.Collections
class ChecklistAdapter(
activity: BaseSimpleActivity,
var items: MutableList<ChecklistItem>,
val listener: ChecklistItemsListener?,
recyclerView: MyRecyclerView,
val showIcons: Boolean,
itemClick: (Any) -> Unit,
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick), ItemTouchHelperContract {
itemClick: (Any) -> Unit = {},
) : MyRecyclerViewListAdapter<ChecklistItem>(
activity = activity, recyclerView = recyclerView, diffUtil = ChecklistItemDiffUtil(), itemClick = itemClick
), ItemTouchHelperContract {
private var touchHelper: ItemTouchHelper? = null
private var startReorderDragListener: StartReorderDragListener
init {
setupDragListener(true)
setHasStableIds(true)
touchHelper = ItemTouchHelper(ItemMoveCallback(this))
touchHelper!!.attachToRecyclerView(recyclerView)
@@ -69,23 +72,21 @@ class ChecklistAdapter(
}
}
override fun getSelectableItemCount() = items.size
override fun getItemId(position: Int) = currentList[position].id.toLong()
override fun getSelectableItemCount() = currentList.size
override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = items.getOrNull(position)?.id
override fun getItemSelectionKey(position: Int) = currentList.getOrNull(position)?.id
override fun getItemKeyPosition(key: Int) = items.indexOfFirst { it.id == key }
override fun getItemKeyPosition(key: Int) = currentList.indexOfFirst { it.id == key }
@SuppressLint("NotifyDataSetChanged")
override fun onActionModeCreated() {
notifyDataSetChanged()
}
override fun onActionModeCreated() = notifyDataSetChanged()
@SuppressLint("NotifyDataSetChanged")
override fun onActionModeDestroyed() {
notifyDataSetChanged()
}
override fun onActionModeDestroyed() = notifyDataSetChanged()
override fun prepareActionMode(menu: Menu) {
val selectedItems = getSelectedItems()
@@ -101,7 +102,7 @@ class ChecklistAdapter(
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
val item = currentList[position]
holder.bindView(item, allowSingleClick = true, allowLongClick = true) { itemView, _ ->
setupView(itemView, item, holder)
}
@@ -109,85 +110,62 @@ class ChecklistAdapter(
bindViewHolder(holder)
}
override fun getItemCount() = items.size
private fun renameChecklistItem() {
val item = getSelectedItems().first()
RenameChecklistItemDialog(activity, item.title) {
val position = getSelectedItemPositions().first()
item.title = it
notifyItemChanged(position)
RenameChecklistItemDialog(activity, item.title) { title ->
val items = currentList.toMutableList()
items[getSelectedItemPositions().first()] = item.copy(title = title)
saveChecklist(items)
finishActMode()
listener?.saveChecklist {
listener.refreshItems()
}
}
}
private fun deleteSelection() {
val removeItems = ArrayList<ChecklistItem>(selectedKeys.size)
val positions = ArrayList<Int>()
selectedKeys.forEach {
val key = it
val items = currentList.toMutableList()
val itemsToRemove = ArrayList<ChecklistItem>(selectedKeys.size)
selectedKeys.forEach { key ->
val position = items.indexOfFirst { it.id == key }
if (position != -1) {
positions.add(position)
val favorite = getItemWithKey(key)
if (favorite != null) {
removeItems.add(favorite)
itemsToRemove.add(favorite)
}
}
}
items.removeAll(removeItems.toSet())
positions.sortDescending()
removeSelectedItems(positions)
listener?.saveChecklist {
if (items.isEmpty()) {
listener.refreshItems()
}
}
items.removeAll(itemsToRemove.toSet())
saveChecklist(items)
}
private fun moveSelectedItemsToTop() {
activity.config.sorting = SORT_BY_CUSTOM
val movedPositions = mutableListOf<Int>()
val items = currentList.toMutableList()
selectedKeys.reversed().forEach { checklistId ->
val position = items.indexOfFirst { it.id == checklistId }
val tempItem = items[position]
items.removeAt(position)
movedPositions.add(position)
items.add(0, tempItem)
}
movedPositions.forEach {
notifyItemMoved(it, 0)
}
listener?.saveChecklist()
saveChecklist(items)
}
private fun moveSelectedItemsToBottom() {
activity.config.sorting = SORT_BY_CUSTOM
val movedPositions = mutableListOf<Int>()
val items = currentList.toMutableList()
selectedKeys.forEach { checklistId ->
val position = items.indexOfFirst { it.id == checklistId }
val tempItem = items[position]
items.removeAt(position)
movedPositions.add(position)
items.add(items.size, tempItem)
}
movedPositions.forEach {
notifyItemMoved(it, items.size - 1)
}
listener?.saveChecklist()
saveChecklist(items)
}
private fun getItemWithKey(key: Int): ChecklistItem? = items.firstOrNull { it.id == key }
private fun getItemWithKey(key: Int): ChecklistItem? = currentList.firstOrNull { it.id == key }
private fun getSelectedItems() = items.filter { selectedKeys.contains(it.id) } as ArrayList<ChecklistItem>
private fun getSelectedItems() = currentList.filter { selectedKeys.contains(it.id) }.toMutableList()
private fun setupView(view: View, checklistItem: ChecklistItem, holder: ViewHolder) {
val isSelected = selectedKeys.contains(checklistItem.id)
@@ -223,6 +201,7 @@ class ChecklistAdapter(
override fun onRowMoved(fromPosition: Int, toPosition: Int) {
activity.config.sorting = SORT_BY_CUSTOM
val items = currentList.toMutableList()
if (fromPosition < toPosition) {
for (i in fromPosition until toPosition) {
Collections.swap(items, i, i + 1)
@@ -232,13 +211,34 @@ class ChecklistAdapter(
Collections.swap(items, i, i - 1)
}
}
notifyItemMoved(fromPosition, toPosition)
saveChecklist(items)
}
override fun onRowSelected(myViewHolder: ViewHolder?) {
override fun onRowSelected(myViewHolder: MyRecyclerViewAdapter.ViewHolder?) {}
override fun onRowClear(myViewHolder: MyRecyclerViewAdapter.ViewHolder?) {
saveChecklist(currentList.toList())
}
override fun onRowClear(myViewHolder: ViewHolder?) {
listener?.saveChecklist()
private fun saveChecklist(items: List<ChecklistItem>) {
listener?.saveChecklist(items) {
listener.refreshItems()
}
}
}
private class ChecklistItemDiffUtil : DiffUtil.ItemCallback<ChecklistItem>() {
override fun areItemsTheSame(
oldItem: ChecklistItem,
newItem: ChecklistItem
) = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: ChecklistItem,
newItem: ChecklistItem
) = oldItem.id == newItem.id
&& oldItem.isDone == newItem.isDone
&& oldItem.title == newItem.title
&& oldItem.dateCreated == newItem.dateCreated
}

View File

@@ -124,7 +124,7 @@ class OpenNoteAdapter(
NoteType.TYPE_CHECKLIST -> {
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
var items = Gson().fromJson<List<ChecklistItem>>(getNoteStoredValue(context), checklistItemType) ?: listOf()
items = items.filter { it.title != null }.let {
items = items.let {
val sorting = context.config.sorting
ChecklistItem.sorting = sorting
if (ChecklistItem.sorting and SORT_BY_CUSTOM == 0) {

View File

@@ -128,11 +128,11 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
checklistItems = note!!.getNoteStoredValue(context)?.ifEmpty { "[]" }?.let { Json.decodeFromString(it) } ?: mutableListOf()
// checklist title can be null only because of the glitch in upgrade to 6.6.0, remove this check in the future
checklistItems = checklistItems.filter { it.title != null }.toMutableList() as ArrayList<ChecklistItem>
checklistItems = checklistItems.toMutableList() as ArrayList<ChecklistItem>
val sorting = context.config.sorting
if (sorting and SORT_BY_CUSTOM == 0) {
checklistItems.sort()
if (context.config?.moveDoneChecklistItems == true) {
if (context.config.moveDoneChecklistItems) {
checklistItems.sortBy { it.isDone }
}
}

View File

@@ -63,8 +63,7 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
items = Gson().fromJson<ArrayList<ChecklistItem>>(storedNote.getNoteStoredValue(requireActivity()), checklistItemType) ?: ArrayList(1)
// checklist title can be null only because of the glitch in upgrade to 6.6.0, remove this check in the future
items = items.filter { it.title != null }.toMutableList() as ArrayList<ChecklistItem>
items = items.toMutableList() as ArrayList<ChecklistItem>
val sorting = config?.sorting ?: 0
if (sorting and SORT_BY_CUSTOM == 0 && config?.moveDoneChecklistItems == true) {
items.sortBy { it.isDone }
@@ -91,7 +90,7 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
)
}
saveChecklist()
saveChecklist(items)
}
private fun setupFragment() {
@@ -173,25 +172,33 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
items.sortBy { it.isDone }
}
}
ChecklistAdapter(
activity = activity as SimpleActivity,
items = items,
listener = this,
recyclerView = binding.checklistList,
showIcons = true
) { item ->
val clickedNote = item as ChecklistItem
clickedNote.isDone = !clickedNote.isDone
saveNote(items.indexOfFirst { it.id == clickedNote.id })
context?.updateWidgets()
refreshItems()
}.apply {
binding.checklistList.adapter = this
var checklistAdapter = binding.checklistList.adapter as? ChecklistAdapter
if (checklistAdapter == null) {
checklistAdapter = ChecklistAdapter(
activity = activity as SimpleActivity,
listener = this,
recyclerView = binding.checklistList,
itemClick = ::toggleCompletion
)
binding.checklistList.adapter = checklistAdapter
}
checklistAdapter.submitList(items.toList())
}
private fun toggleCompletion(any: Any) {
val item = any as ChecklistItem
val index = items.indexOf(item)
if (index != -1) {
items[index] = item.copy(isDone = !item.isDone)
saveNote {
loadNoteById(noteId)
}
}
}
private fun saveNote(refreshIndex: Int = -1, callback: () -> Unit = {}) {
private fun saveNote(callback: () -> Unit = {}) {
if (note == null) {
return
}
@@ -205,12 +212,6 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
}
if (note != null) {
if (refreshIndex != -1) {
binding.checklistList.post {
binding.checklistList.adapter?.notifyItemChanged(refreshIndex)
}
}
note!!.value = getChecklistItems()
ensureBackgroundThread {
@@ -237,7 +238,8 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
fun getChecklistItems() = Gson().toJson(items)
override fun saveChecklist(callback: () -> Unit) {
override fun saveChecklist(updatedItems: List<ChecklistItem>, callback: () -> Unit) {
items = updatedItems.toMutableList()
saveNote(callback = callback)
}

View File

@@ -76,7 +76,7 @@ class Config(context: Context) : BaseConfig(context) {
set(lastCreatedNoteType) = prefs.edit().putInt(LAST_CREATED_NOTE_TYPE, lastCreatedNoteType).apply()
var moveDoneChecklistItems: Boolean
get() = prefs.getBoolean(MOVE_DONE_CHECKLIST_ITEMS, true)
get() = prefs.getBoolean(MOVE_DONE_CHECKLIST_ITEMS, false)
set(moveDoneChecklistItems) = prefs.edit().putBoolean(MOVE_DONE_CHECKLIST_ITEMS, moveDoneChecklistItems).apply()
fun getTextGravity() = when (gravity) {

View File

@@ -1,7 +1,9 @@
package org.fossify.notes.interfaces
import org.fossify.notes.models.ChecklistItem
interface ChecklistItemsListener {
fun refreshItems()
fun saveChecklist(callback: () -> Unit = {})
fun saveChecklist(updatedItems: List<ChecklistItem>, callback: () -> Unit = {})
}

View File

@@ -9,8 +9,8 @@ import org.fossify.notes.helpers.CollatorBasedComparator
data class ChecklistItem(
val id: Int,
val dateCreated: Long = 0L,
var title: String,
var isDone: Boolean
val title: String,
val isDone: Boolean
) : Comparable<ChecklistItem> {
companion object {