mirror of
https://github.com/FossifyOrg/Notes.git
synced 2026-03-03 14:06:21 -05:00
Use list adapter for checklists
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 = {})
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user