Skip to content

Commit

Permalink
Support batch deletion in Memo app:
Browse files Browse the repository at this point in the history
  • Loading branch information
tuancoltech committed Sep 17, 2024
1 parent 1be9241 commit 4752e78
Show file tree
Hide file tree
Showing 25 changed files with 486 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ data class GraphicNote(
val svg: SVG? = null,
@IgnoredOnParcel
override var resource: Resource? = null,
override var pendingForDelete: Boolean = false
override var pendingForDelete: Boolean = false,
override var selected: Boolean = false
) : Note, Parcelable
1 change: 1 addition & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ interface Note {
val description: String
var resource: Resource?
var pendingForDelete: Boolean
var selected: Boolean
}
3 changes: 2 additions & 1 deletion app/src/main/java/dev/arkbuilders/arkmemo/models/TextNote.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ data class TextNote (
val text: String = "",
@IgnoredOnParcel
override var resource: Resource? = null,
override var pendingForDelete: Boolean = false
override var pendingForDelete: Boolean = false,
override var selected: Boolean = false
): Note, Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ class VoiceNote(
override var pendingForDelete: Boolean = false,
var isPlaying: Boolean = false,
var currentPlayingPos: Int = 0,
var currentMaxAmplitude: Int = 0
var currentMaxAmplitude: Int = 0,
override var selected: Boolean = false
): Note, Parcelable
2 changes: 2 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ interface NotesRepo<Note> {
suspend fun read(): List<Note>

suspend fun delete(note: Note)

suspend fun delete(notes: List<Note>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ class NotesRepoHelper @Inject constructor(
return UserNoteProperties(title, description)
}

suspend fun deleteNote(notes: List<Note>): Unit = withContext(Dispatchers.IO) {
notes.forEach { note ->
deleteNote(note)
}
}

suspend fun deleteNote(note: Note): Unit = withContext(Dispatchers.IO) {
val id = note.resource?.id

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class GraphicNotesRepo @Inject constructor(
helper.deleteNote(note)
}

override suspend fun delete(notes: List<GraphicNote>) {
helper.deleteNote(notes)
}

override suspend fun read(): List<GraphicNote> = withContext(iODispatcher) {
readStorage()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class TextNotesRepo @Inject constructor(
write(note) { callback(it) }
}

override suspend fun delete(notes: List<TextNote>) {
helper.deleteNote(notes)
}

override suspend fun delete(note: TextNote) {
helper.deleteNote(note)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class VoiceNotesRepo @Inject constructor(
readStorage()
}

override suspend fun delete(notes: List<VoiceNote>) {
helper.deleteNote(notes)
}

override suspend fun delete(note: VoiceNote) {
helper.deleteNote(note)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ package dev.arkbuilders.arkmemo.ui.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.RecyclerView
import by.kirich1409.viewbindingdelegate.viewBinding
import dev.arkbuilders.arkmemo.R
Expand Down Expand Up @@ -35,13 +39,21 @@ class NotesListAdapter(
): RecyclerView.Adapter<NotesListAdapter.NoteViewHolder>() {

private lateinit var activity: MainActivity
private var mActionMode = false

lateinit var observeItemSideEffect: () -> ArkMediaPlayerSideEffect
lateinit var observeItemState: () -> ArkMediaPlayerState

private var isFromSearch: Boolean = false
private var searchKeyWord: String = ""

var onItemLongPressed: ((pos: Int, note: Note) -> Unit)? = null
var onItemClicked: (() -> Unit)? = null

private val selectedNoteCount by lazy { MutableLiveData<Int>() }
val observableSelectedNoteCount by lazy { selectedNoteCount }
val selectedNotedForDelete = mutableListOf<Note>()

fun setActivity(activity: AppCompatActivity) {
this.activity = activity as MainActivity
}
Expand Down Expand Up @@ -108,6 +120,13 @@ class NotesListAdapter(
} else {
holder.tvDelete.gone()
}

holder.cbDelete.isChecked = note.selected
if (mActionMode) {
holder.cbDelete.visible()
} else {
holder.cbDelete.gone()
}
}

override fun getItemCount() = notes.size
Expand Down Expand Up @@ -173,6 +192,27 @@ class NotesListAdapter(
this.notes = notes
}

fun toggleActionMode() {
mActionMode = !mActionMode
notes.forEach { it.selected = false }
selectedNoteCount.postValue(0)
notifyDataSetChanged()
}

fun toggleSelectAllItems(selected: Boolean) {
notes.forEach { it.selected = selected }
selectedNotedForDelete.clear()
selectedNoteCount.postValue(
if (selected) {
selectedNotedForDelete.addAll(notes)
notes.size
} else {
0
}
)
notifyDataSetChanged()
}

inner class NoteViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
private val binding by viewBinding {
AdapterTextNoteBinding.bind(itemView)
Expand All @@ -185,6 +225,7 @@ class NotesListAdapter(
val tvPlayingPosition = binding.layoutAudioView.tvPlayingPosition
val canvasGraphicThumb = binding.canvasGraphicThumb
val tvDelete = binding.tvDelete
val cbDelete = binding.cbDelete

private val clickNoteToEditListener = View.OnClickListener {
var tag = EditTextNotesFragment.TAG
Expand All @@ -199,11 +240,39 @@ class NotesListAdapter(
tag = ArkRecorderFragment.TAG
}
}
onItemClicked?.invoke()
activity.replaceFragment(activity.fragment, tag)
}

private val noteCheckedListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
if (!buttonView.isPressed) return@OnCheckedChangeListener
val selectedNote = notes[bindingAdapterPosition]
selectedNote.selected = isChecked
if (isChecked) {
selectedNoteCount.value?.let { count ->
selectedNoteCount.postValue(count + 1)
}
selectedNotedForDelete.add(selectedNote)
} else {
selectedNoteCount.value?.let { count ->
selectedNoteCount.postValue(count - 1)
}
selectedNotedForDelete.remove(selectedNote)
}

buttonView.post {
notifyItemChanged(bindingAdapterPosition)
}
}

init {
binding.root.setOnClickListener(clickNoteToEditListener)
binding.root.setOnLongClickListener {
onItemLongPressed?.invoke(bindingAdapterPosition, notes[bindingAdapterPosition])
true
}
binding.cbDelete.setOnCheckedChangeListener(noteCheckedListener)
binding.layoutAudioView.root.setBackgroundResource(R.drawable.bg_audio_view_note_item)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import dev.arkbuilders.arkmemo.databinding.DialogCommonActionBinding
* This is a common action dialog that can be used inside app.
* It's a basic dialog with customizable title, message, one positive button and one negative button
*/
class CommonActionDialog(@StringRes private val title: Int,
@StringRes private val message: Int,
class CommonActionDialog(private val title: String,
private val message: String,
@StringRes private val positiveText: Int,
@StringRes private val negativeText: Int,
private val isAlert: Boolean = false,
Expand Down Expand Up @@ -46,8 +46,8 @@ class CommonActionDialog(@StringRes private val title: Int,
mBinding.tvPositive.setBackgroundResource(R.drawable.bg_red_button)
}

mBinding.tvTitle.setText(title)
mBinding.tvMessage.setText(message)
mBinding.tvTitle.text = title
mBinding.tvMessage.text = message
mBinding.tvPositive.setText(positiveText)
mBinding.tvNegative.setText(negativeText)
mBinding.ivClose.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ class ArkRecorderFragment: BaseEditNoteFragment() {
&& (arkRecorderViewModel.isRecordExisting() ||
File(getCurrentRecordingPath()).length() > 0L)) {

CommonActionDialog(title = R.string.dialog_replace_recording_title,
message = R.string.dialog_replace_recording_message,
CommonActionDialog(title = getString(R.string.dialog_replace_recording_title),
message = getString(R.string.dialog_replace_recording_message),
positiveText = R.string.dialog_replace_recording_positive_text,
negativeText = R.string.discard,
onPositiveClick = {
Expand Down Expand Up @@ -200,15 +200,16 @@ class ArkRecorderFragment: BaseEditNoteFragment() {
title = title.ifEmpty { defaultNoteTitle },
path = arkRecorderViewModel.getRecordingPath()
)
CommonActionDialog(title = R.string.delete_note,
message = R.string.ark_memo_delete_warn,
CommonActionDialog(title = getString(R.string.delete_note),
message = resources.getQuantityString(R.plurals.delete_batch_note_message, 1),
positiveText = R.string.action_delete,
negativeText = R.string.ark_memo_cancel,
isAlert = true,
onPositiveClick = {
notesViewModel.onDeleteConfirmed(note)
toast(requireContext(), getString(R.string.note_deleted))
activity.onBackPressedDispatcher.onBackPressed()
notesViewModel.onDeleteConfirmed(listOf(note)) {
toast(requireContext(), getString(R.string.note_deleted))
activity.onBackPressedDispatcher.onBackPressed()
}
}, onNegativeClicked = {
}).show(parentFragmentManager, CommonActionDialog.TAG)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ abstract class BaseEditNoteFragment: Fragment() {

private fun showSaveNoteDialog() {
val saveNoteDialog = CommonActionDialog(
title = R.string.dialog_save_note_title,
message = R.string.dialog_save_note_message,
title = getString(R.string.dialog_save_note_title),
message = getString(R.string.dialog_save_note_message),
positiveText = R.string.save,
negativeText = R.string.discard,
isAlert = false,
Expand All @@ -119,15 +119,16 @@ abstract class BaseEditNoteFragment: Fragment() {

fun showDeleteNoteDialog(note: Note) {
CommonActionDialog(
title = R.string.delete_note,
message = R.string.ark_memo_delete_warn ,
title = getString(R.string.delete_note),
message = resources.getQuantityString(R.plurals.delete_batch_note_message, 1),
positiveText = R.string.action_delete,
negativeText = R.string.ark_memo_cancel,
isAlert = true,
onPositiveClick = {
notesViewModel.onDeleteConfirmed(note)
hostActivity.onBackPressedDispatcher.onBackPressed()
toast(requireContext(), getString(R.string.note_deleted))
notesViewModel.onDeleteConfirmed(listOf(note)) {
hostActivity.onBackPressedDispatcher.onBackPressed()
toast(requireContext(), getString(R.string.note_deleted))
}
}, onNegativeClicked = {
}).show(parentFragmentManager, CommonActionDialog.TAG)
}
Expand Down
Loading

0 comments on commit 4752e78

Please sign in to comment.