Skip to content

Commit

Permalink
Added multiselect delete in manageNotesType
Browse files Browse the repository at this point in the history
solved some bugs and disabled rename,edit and delete buttons

remove useless logs
  • Loading branch information
jainv4156 committed Sep 25, 2024
1 parent fab5a8c commit 02a51ad
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 43 deletions.
99 changes: 96 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
import androidx.recyclerview.widget.RecyclerView
import anki.notetypes.copy
import com.google.android.material.floatingactionbutton.FloatingActionButton
Expand All @@ -51,12 +53,18 @@ import com.ichi2.utils.positiveButton
import com.ichi2.utils.show
import com.ichi2.utils.title

class ManageNotetypes : AnkiActivity() {
class ManageNotetypes : AnkiActivity(), NoteTypeAdapterCallbacks {
private lateinit var actionBar: ActionBar
private lateinit var noteTypesList: RecyclerView

private var currentNotetypes: List<ManageNoteTypeUiModel> = emptyList()

lateinit var toolbar: Toolbar
private var toDeleteList: List<Long> = emptyList()
private var isInMultiSelectMode = false
private fun getIsInMultiSelectMode(): Boolean {
return isInMultiSelectMode
}
private val notetypesAdapter: NotetypesAdapter by lazy {
NotetypesAdapter(
this@ManageNotetypes,
Expand All @@ -70,6 +78,8 @@ class ManageNotetypes : AnkiActivity() {
},
onEditCards = { launchForChanges<CardTemplateEditor>(mapOf("modelId" to it.id)) },
onRename = ::renameNotetype,
callback = this,
getIsInMultiSelectMode = ::getIsInMultiSelectMode,
onDelete = ::deleteNotetype
)
}
Expand All @@ -89,6 +99,7 @@ class ManageNotetypes : AnkiActivity() {
setTitle(R.string.model_browser_label)
setContentView(R.layout.activity_manage_note_types)
actionBar = enableToolbar()
toolbar = findViewById(R.id.toolbar)
noteTypesList = findViewById<RecyclerView?>(R.id.note_types_list).apply {
adapter = notetypesAdapter
}
Expand All @@ -100,8 +111,7 @@ class ManageNotetypes : AnkiActivity() {
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.search, menu)

menuInflater.inflate(R.menu.menu_manage_notes, menu)
val searchItem = menu.findItem(R.id.search_item)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView = searchItem?.actionView as? SearchView
Expand All @@ -125,8 +135,21 @@ class ManageNotetypes : AnkiActivity() {
return true
}
})

launchCatchingTask {
menu.findItem(R.id.action_delete_notes).isVisible = toDeleteList.isNotEmpty() && isInMultiSelectMode
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_delete_notes -> {
deleteSelectedNotetype()
true
}
else -> super.onOptionsItemSelected(item)
}
}

@SuppressLint("CheckResult")
private fun renameNotetype(manageNoteTypeUiModel: ManageNoteTypeUiModel) {
Expand Down Expand Up @@ -167,6 +190,28 @@ class ManageNotetypes : AnkiActivity() {
}
}

private fun deleteSelectedNotetype() {
val selectedItems = toDeleteList
AlertDialog.Builder(this@ManageNotetypes).show {
title(R.string.model_browser_delete)
message(R.string.model_delete_warning)
positiveButton(R.string.dialog_positive_delete) {
disableMultiSelectMode()
launchCatchingTask {
withProgress {
withCol {
selectedItems.forEach { item ->
removeNotetype(item)
}
}
}
runAndRefreshAfter()
}
}
negativeButton(R.string.dialog_cancel)
}
}

private fun deleteNotetype(manageNoteTypeUiModel: ManageNoteTypeUiModel) {
launchCatchingTask {
val messageResourceId: Int? = if (userAcceptsSchemaChange()) {
Expand Down Expand Up @@ -236,4 +281,52 @@ class ManageNotetypes : AnkiActivity() {
else -> throw IllegalArgumentException("Unexpected value type: ${newExtra.value}")
}
}

override fun enableMultiSelectMode() {
isInMultiSelectMode = true
toolbar.setNavigationOnClickListener {
disableMultiSelectMode()
}
notetypesAdapter.notifyItemRangeChanged(0, notetypesAdapter.itemCount, "payload_enable_checkbox_visibility")
}

private fun disableMultiSelectMode() {
toDeleteList = emptyList()
isInMultiSelectMode = false

toolbar.setNavigationOnClickListener {
finish()
}
notetypesAdapter.notifyItemRangeChanged(0, notetypesAdapter.itemCount, "payload_disable_checkbox_visibility")
invalidateMenu()
}

override fun isToDeleteListContains(id: Long): Boolean {
return toDeleteList.contains(id)
}

override fun setCheckBoxSelectionOnCLick(id: Long, position: Int) {
if (toDeleteList.contains(id)) {
toDeleteList = toDeleteList.minus(id)

/** deselecting all checkbox will turnoff the multiselect mode*/
if (toDeleteList.isEmpty()) {
disableMultiSelectMode()
} else {
notetypesAdapter.notifyItemChanged(position, "payload_deselect_checkbox")
}
} else {
toDeleteList = toDeleteList.plus(id)
notetypesAdapter.notifyItemChanged(position, "payload_select_checkbox")
}
invalidateMenu()
}

override fun setCheckBoxSelectionOnStart(id: Long): Boolean {
return if (toDeleteList.contains(id)) {
true
} else {
false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/****************************************************************************************
* Copyright (c) 2022 Vaibhav Jain <[email protected]> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 3 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
package com.ichi2.anki.notetype

interface NoteTypeAdapterCallbacks {
fun enableMultiSelectMode()
fun isToDeleteListContains(id: Long): Boolean
fun setCheckBoxSelectionOnCLick(id: Long, position: Int)
fun setCheckBoxSelectionOnStart(id: Long): Boolean
}
103 changes: 100 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/notetype/NotetypeAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CheckBox
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.ichi2.anki.R

private val notetypeNamesAndCountDiff =
Expand All @@ -46,6 +48,8 @@ internal class NotetypesAdapter(
private val onShowFields: (ManageNoteTypeUiModel) -> Unit,
private val onEditCards: (ManageNoteTypeUiModel) -> Unit,
private val onRename: (ManageNoteTypeUiModel) -> Unit,
private val callback: NoteTypeAdapterCallbacks,
private val getIsInMultiSelectMode: () -> Boolean,
private val onDelete: (ManageNoteTypeUiModel) -> Unit
) : ListAdapter<ManageNoteTypeUiModel, NotetypeViewHolder>(notetypeNamesAndCountDiff) {
private val layoutInflater = LayoutInflater.from(context)
Expand All @@ -56,44 +60,137 @@ internal class NotetypesAdapter(
onDelete = onDelete,
onRename = onRename,
onEditCards = onEditCards,
callback = callback,
getIsInMultiSelectMode = getIsInMultiSelectMode,
onShowFields = onShowFields
)
}

override fun onBindViewHolder(holder: NotetypeViewHolder, position: Int) {
holder.bind(getItem(position))
}

override fun onBindViewHolder(holder: NotetypeViewHolder, position: Int, payloads: List<Any>) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
} else {
for (payload in payloads) {
when (payload) {
"payload_enable_checkbox_visibility" -> {
holder.applyMultiSelectMode(getItem(position))
}
"payload_disable_checkbox_visibility" -> {
holder.removeMultiSelectMode()
}
"payload_select_checkbox" -> {
holder.selectCheckBox()
}
"payload_deselect_checkbox" -> {
holder.deselectCheckBox()
}
}
}
}
}
}

internal class NotetypeViewHolder(
rowView: View,
onShowFields: (ManageNoteTypeUiModel) -> Unit,
private val onShowFields: (ManageNoteTypeUiModel) -> Unit,
private val callback: NoteTypeAdapterCallbacks,
onEditCards: (ManageNoteTypeUiModel) -> Unit,
onRename: (ManageNoteTypeUiModel) -> Unit,
getIsInMultiSelectMode: () -> Boolean,
onDelete: (ManageNoteTypeUiModel) -> Unit
) : RecyclerView.ViewHolder(rowView) {
val name: TextView = rowView.findViewById(R.id.note_name)
val useCount: TextView = rowView.findViewById(R.id.note_use_count)
private val useCount: TextView = rowView.findViewById(R.id.note_use_count)
private val btnDelete: Button = rowView.findViewById(R.id.note_delete)
private val btnRename: Button = rowView.findViewById(R.id.note_rename)
private val btnEditCards: Button = rowView.findViewById(R.id.note_edit_cards)
private var mManageNoteTypeUiModel: ManageNoteTypeUiModel? = null
private val resources = rowView.context.resources
private val isInMultiSelectMode = getIsInMultiSelectMode
private val selectedItemCheckbox: CheckBox = rowView.findViewById(R.id.selected_item_checkbox)
private val editCardButton: MaterialButton = rowView.findViewById(R.id.note_edit_cards)
private val renameCardButton: MaterialButton = rowView.findViewById(R.id.note_rename)
private val deleteCardButton: MaterialButton = rowView.findViewById(R.id.note_delete)

init {
rowView.setOnClickListener { mManageNoteTypeUiModel?.let(onShowFields) }
btnEditCards.setOnClickListener { mManageNoteTypeUiModel?.let(onEditCards) }
btnDelete.setOnClickListener { mManageNoteTypeUiModel?.let(onDelete) }
btnRename.setOnClickListener { mManageNoteTypeUiModel?.let(onRename) }
}

fun bind(manageNoteTypeUiModel: ManageNoteTypeUiModel) {
if (isInMultiSelectMode()) {
applyMultiSelectMode(manageNoteTypeUiModel)
} else {
removeMultiSelectMode()
}
this.mManageNoteTypeUiModel = manageNoteTypeUiModel
name.text = manageNoteTypeUiModel.name
useCount.text = resources.getQuantityString(
R.plurals.model_browser_of_type,
manageNoteTypeUiModel.useCount,
manageNoteTypeUiModel.useCount
)
itemView.setOnLongClickListener {
callback.enableMultiSelectMode()
callback.setCheckBoxSelectionOnCLick(manageNoteTypeUiModel.id, bindingAdapterPosition)
true
}
}
fun applyMultiSelectMode(manageNoteTypeUiModel: ManageNoteTypeUiModel) {
showCheckBox(selectedItemCheckbox)
if (callback.setCheckBoxSelectionOnStart(manageNoteTypeUiModel.id)) {
selectCheckBox()
} else {
deselectCheckBox()
}
disableEditDeleteRenameButton()
itemView.setOnClickListener {
callback.setCheckBoxSelectionOnCLick(manageNoteTypeUiModel.id, bindingAdapterPosition)
}
}
fun removeMultiSelectMode() {
enableEditDeleteRenameButton()
hideCheckBox(selectedItemCheckbox)
selectedItemCheckbox.isChecked = false
itemView.setOnClickListener { mManageNoteTypeUiModel?.let(onShowFields) }
}
fun selectCheckBox() {
selectedItemCheckbox.isChecked = true
}
fun deselectCheckBox() {
selectedItemCheckbox.isChecked = false
}
private fun hideCheckBox(checkBox: CheckBox) {
checkBox.visibility = View.GONE
}
private fun showCheckBox(checkBox: CheckBox) {
checkBox.visibility = View.VISIBLE
}
private fun disableEditDeleteRenameButton() {
editCardButton.apply {
visibility = View.GONE
}
renameCardButton.apply {
visibility = View.GONE
}
deleteCardButton.apply {
visibility = View.GONE
}
}
private fun enableEditDeleteRenameButton() {
editCardButton.apply {
visibility = View.VISIBLE
}
renameCardButton.apply {
visibility = View.VISIBLE
}
deleteCardButton.apply {
visibility = View.VISIBLE
}
}
}
Loading

0 comments on commit 02a51ad

Please sign in to comment.