diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt b/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt index 5ab1dc85..e69220d0 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt @@ -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 \ No newline at end of file diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt b/app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt index 2ad3cfe5..85ecbefc 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt @@ -7,4 +7,5 @@ interface Note { val description: String var resource: Resource? var pendingForDelete: Boolean + var selected: Boolean } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/models/TextNote.kt b/app/src/main/java/dev/arkbuilders/arkmemo/models/TextNote.kt index 715e946d..3c52fce7 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/models/TextNote.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/models/TextNote.kt @@ -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 diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/models/VoiceNote.kt b/app/src/main/java/dev/arkbuilders/arkmemo/models/VoiceNote.kt index 9f9f1429..23de74b8 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/models/VoiceNote.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/models/VoiceNote.kt @@ -16,5 +16,6 @@ class VoiceNote( var path: Path = createTempFile(), @IgnoredOnParcel override var resource: Resource? = null, - override var pendingForDelete: Boolean = false + override var pendingForDelete: Boolean = false, + override var selected: Boolean = false ): Note, Parcelable \ No newline at end of file diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepo.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepo.kt index 7f12eaa3..03cda8de 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepo.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepo.kt @@ -11,4 +11,6 @@ interface NotesRepo { suspend fun read(): List suspend fun delete(note: Note) + + suspend fun delete(notes: List) } \ No newline at end of file diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepoHelper.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepoHelper.kt index 924d6214..eaa92759 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepoHelper.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/NotesRepoHelper.kt @@ -80,6 +80,12 @@ class NotesRepoHelper @Inject constructor( return UserNoteProperties(title, description) } + suspend fun deleteNote(notes: List): Unit = withContext(Dispatchers.IO) { + notes.forEach { note -> + deleteNote(note) + } + } + suspend fun deleteNote(note: Note): Unit = withContext(Dispatchers.IO) { val id = note.resource?.id diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt index f820df82..7d77d225 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt @@ -47,6 +47,10 @@ class GraphicNotesRepo @Inject constructor( helper.deleteNote(note) } + override suspend fun delete(notes: List) { + helper.deleteNote(notes) + } + override suspend fun read(): List = withContext(iODispatcher) { readStorage() } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/text/TextNotesRepo.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/text/TextNotesRepo.kt index 12ecba95..c78799a9 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/text/TextNotesRepo.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/text/TextNotesRepo.kt @@ -42,6 +42,10 @@ class TextNotesRepo @Inject constructor( write(note) { callback(it) } } + override suspend fun delete(notes: List) { + helper.deleteNote(notes) + } + override suspend fun delete(note: TextNote) { helper.deleteNote(note) } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/voices/VoiceNotesRepo.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/voices/VoiceNotesRepo.kt index 9d758977..4d16e74f 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/voices/VoiceNotesRepo.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/voices/VoiceNotesRepo.kt @@ -41,6 +41,10 @@ class VoiceNotesRepo @Inject constructor( readStorage() } + override suspend fun delete(notes: List) { + helper.deleteNote(notes) + } + override suspend fun delete(note: VoiceNote) { helper.deleteNote(note) } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt index 09640229..1e1aaaf5 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt @@ -3,9 +3,12 @@ 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.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 @@ -34,6 +37,7 @@ class NotesListAdapter( ): RecyclerView.Adapter() { private lateinit var activity: MainActivity + private var mActionMode = false lateinit var observeItemSideEffect: () -> ArkMediaPlayerSideEffect lateinit var observeItemState: () -> ArkMediaPlayerState @@ -41,6 +45,13 @@ class NotesListAdapter( 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() } + val observableSelectedNoteCount = selectedNoteCount as LiveData + val selectedNotedForDelete = mutableListOf() + fun setActivity(activity: AppCompatActivity) { this.activity = activity as MainActivity } @@ -88,6 +99,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 @@ -145,6 +163,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) @@ -156,6 +195,7 @@ class NotesListAdapter( val layoutAudioView = binding.layoutAudioView val canvasGraphicThumb = binding.canvasGraphicThumb val tvDelete = binding.tvDelete + val cbDelete = binding.cbDelete private val clickNoteToEditListener = View.OnClickListener { var tag = EditTextNotesFragment.TAG @@ -170,11 +210,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) } } } \ No newline at end of file diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/dialogs/CommonActionDialog.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/dialogs/CommonActionDialog.kt index 1dda9126..e6f352ed 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/dialogs/CommonActionDialog.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/dialogs/CommonActionDialog.kt @@ -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, @@ -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 { diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/ArkRecorderFragment.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/ArkRecorderFragment.kt index 0b86a31e..54af7563 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/ArkRecorderFragment.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/ArkRecorderFragment.kt @@ -155,8 +155,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 = { @@ -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) } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/BaseEditNoteFragment.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/BaseEditNoteFragment.kt index 64d1395c..0dc5d3ea 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/BaseEditNoteFragment.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/BaseEditNoteFragment.kt @@ -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, @@ -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) } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt index 18b1e7bc..b8da6124 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt @@ -45,6 +45,9 @@ class NotesFragment: Fragment() { private var notesAdapter: NotesListAdapter? = null private var showingFloatingButtons = false + private var mIsActionMode = false + + private var selectedCountForDelete = 0 private val newTextNoteClickListener = View.OnClickListener { onFloatingActionButtonClicked() @@ -77,15 +80,16 @@ class NotesFragment: Fragment() { } ?: return binding.rvPinnedNotes.adapter?.notifyItemChanged(deletePosition) - 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(noteToDelete) - toast(requireContext(), getString(R.string.note_deleted)) - binding.rvPinnedNotes.adapter?.notifyItemRemoved(deletePosition) + notesViewModel.onDeleteConfirmed(listOf(noteToDelete)) { + toast(requireContext(), getString(R.string.note_deleted)) + binding.rvPinnedNotes.adapter?.notifyItemRemoved(deletePosition) + } }, onNegativeClicked = { noteToDelete.pendingForDelete = false binding.rvPinnedNotes.adapter?.notifyItemChanged(deletePosition) @@ -164,6 +168,7 @@ class NotesFragment: Fragment() { } ) + observeSelectedNoteForDelete() } else { notesAdapter?.setNotes(notes) @@ -175,6 +180,9 @@ class NotesFragment: Fragment() { handleSideEffect = { effect -> notesAdapter?.observeItemSideEffect = { effect } } ) notesAdapter?.setActivity(activity) + notesAdapter?.onItemLongPressed = {pos, note -> + toggleActionMode() + } binding.rvPinnedNotes.apply { this.layoutManager = layoutManager this.adapter = notesAdapter @@ -200,6 +208,16 @@ class NotesFragment: Fragment() { super.onResume() activity.fragment = this observeClipboardContent() + if (notesAdapter?.observableSelectedNoteCount?.hasActiveObservers() == false) { + observeSelectedNoteForDelete() + } + } + + override fun onStop() { + super.onStop() + if (mIsActionMode) { + toggleActionMode() + } } private fun createTextNote() { @@ -280,6 +298,89 @@ class NotesFragment: Fragment() { } } + private fun toggleActionMode() { + if (mIsActionMode) { + binding.groupActionModeTexts.gone() + binding.layoutBottomControl.visible() + } else { + binding.groupActionModeTexts.visible() + updateSelectStateTexts(selectedCountForDelete) + binding.layoutBottomControl.gone() + binding.tvActionModeCancel.setOnClickListener { + toggleActionMode() + } + binding.tvActionModeSelectAll.setOnClickListener { + + if (selectedCountForDelete == notesAdapter?.getNotes()?.size) { + notesAdapter?.toggleSelectAllItems(selected = false) + } else { + notesAdapter?.toggleSelectAllItems(selected = true) + } + updateSelectStateTexts(selectedCountForDelete) + } + binding.btnDelete.setOnClickListener { + showBatchDeletionDialog() + } + } + (binding.rvPinnedNotes.adapter as? NotesListAdapter)?.toggleActionMode() + mIsActionMode = !mIsActionMode + } + + private fun showBatchDeletionDialog() { + CommonActionDialog(title = resources.getQuantityString(R.plurals.delete_note_count, selectedCountForDelete, selectedCountForDelete), + message = resources.getQuantityString(R.plurals.delete_batch_note_message, selectedCountForDelete), + positiveText = R.string.action_delete, + negativeText = R.string.ark_memo_cancel, + isAlert = true, + onPositiveClick = { + binding.pbLoading.visible() + notesViewModel.onDeleteConfirmed(notesAdapter?.selectedNotedForDelete ?: emptyList()) { + binding.pbLoading.gone() + toast(requireContext(), getString(R.string.note_deleted)) + binding.rvPinnedNotes.adapter?.notifyDataSetChanged() + toggleActionMode() + } + }, + onNegativeClicked = {}, + onCloseClicked = {} + ).show(childFragmentManager, CommonActionDialog.TAG) + } + + private fun updateSelectStateTexts(selectedCount: Int) { + binding.tvSelectedNoteCount.text = resources.getQuantityString( + R.plurals.selected_note_count, selectedCount, selectedCount + ) + binding.tvActionModeSelectAll.text = + if (selectedCount == (notesAdapter?.getNotes()?.size ?: 0)) { + getString(R.string.deselect_all) + } else { + getString(R.string.select_all) + } + } + + private fun changeDeleteButtonState(enabled: Boolean) { + if (enabled) { + binding.btnDelete.isClickable = true + binding.btnDelete.alpha = 1f + } else { + binding.btnDelete.isClickable = false + binding.btnDelete.alpha = 0.4f + } + } + + private fun observeSelectedNoteForDelete() { + notesAdapter?.observableSelectedNoteCount?.observe(viewLifecycleOwner) { count -> + selectedCountForDelete = count + updateSelectStateTexts(count) + + if (count > 0) { + changeDeleteButtonState(enabled = true) + } else { + changeDeleteButtonState(enabled = false) + } + } + } + companion object { const val TAG = "NotesFragment" } diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/viewmodels/NotesViewModel.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/viewmodels/NotesViewModel.kt index 4b0b56f1..de7e176b 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/viewmodels/NotesViewModel.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/viewmodels/NotesViewModel.kt @@ -89,7 +89,7 @@ class NotesViewModel @Inject constructor( || result == SaveNoteResult.SUCCESS_UPDATED) { if (result == SaveNoteResult.SUCCESS_NEW) { - parentNote?.let { onDeleteConfirmed(parentNote) } + parentNote?.let { onDeleteConfirmed(listOf(parentNote)){} } } add(note, noteResId) @@ -119,13 +119,19 @@ class NotesViewModel @Inject constructor( } } - fun onDeleteConfirmed(note: Note) { + fun onDeleteConfirmed(notes: List, onSuccess: () -> Unit) { viewModelScope.launch(iODispatcher) { - remove(note) - when (note) { - is TextNote -> textNotesRepo.delete(note) - is GraphicNote -> graphicNotesRepo.delete(note) - is VoiceNote -> voiceNotesRepo.delete(note) + notes.forEach { note -> + when (note) { + is TextNote -> textNotesRepo.delete(note) + is GraphicNote -> graphicNotesRepo.delete(note) + is VoiceNote -> voiceNotesRepo.delete(note) + } + } + this@NotesViewModel.notes.value = this@NotesViewModel.notes.value.toMutableList() + .apply { removeAll(notes) } + withContext(Dispatchers.Main) { + onSuccess.invoke() } } } diff --git a/app/src/main/res/drawable/bg_audio_view_note_item.xml b/app/src/main/res/drawable/bg_audio_view_note_item.xml new file mode 100644 index 00000000..739f49e8 --- /dev/null +++ b/app/src/main/res/drawable/bg_audio_view_note_item.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/font/font.xml b/app/src/main/res/font/font.xml new file mode 100644 index 00000000..c06f89eb --- /dev/null +++ b/app/src/main/res/font/font.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_text_note.xml b/app/src/main/res/layout/adapter_text_note.xml index d4d2b3e8..155f2745 100644 --- a/app/src/main/res/layout/adapter_text_note.xml +++ b/app/src/main/res/layout/adapter_text_note.xml @@ -4,96 +4,121 @@ android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:background="@drawable/bg_big_radius" android:clickable="true" android:layout_marginBottom="@dimen/note_item_padding" android:foreground="?attr/selectableItemBackgroundBorderless"> - - - + app:layout_constraintBottom_toBottomOf="parent" + android:buttonTint="@color/yellow_700" + android:visibility="gone"/> - + app:layout_constraintTop_toTopOf="parent" + android:background="@drawable/bg_big_radius" + app:layout_constraintBottom_toBottomOf="parent"> - + - + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_common_action.xml b/app/src/main/res/layout/dialog_common_action.xml index d7cc5f62..f5e6f755 100644 --- a/app/src/main/res/layout/dialog_common_action.xml +++ b/app/src/main/res/layout/dialog_common_action.xml @@ -3,6 +3,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_gravity="center" android:fitsSystemWindows="true"> @@ -38,7 +39,7 @@ app:layout_constraintStart_toStartOf="@+id/tv_title" app:layout_constraintTop_toBottomOf="@+id/iv_close" app:layout_constraintEnd_toEndOf="@+id/iv_close" - android:text="@string/ark_memo_delete_warn" + tools:text="Are you sure you want to delete this note? This action cannot be undone." android:id="@+id/tv_message"/> + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/barrier_top_note_list"> + android:layout_height="wrap_content" + xmlns:tools="http://schemas.android.com/tools"> + + + + #FFFAEB #FEF0C7 #FEC84B + #DC6803 #B54708 #344054 #B54708 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fd8f8adb..ec642761 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,7 +27,6 @@ Nothing to paste OK Cancel - Are you sure you want to delete this note? This action cannot be undone. Note already exists Note saved successfully Title @@ -102,4 +101,19 @@ Will be available soon! Invalid recording file + + %d Item selected + %d Items selected + + + Delete %d note + Delete %d notes + + + Are you sure you want to delete this note? This action cannot be undone. + Are you sure you want to delete these notes? This action cannot be undone. + + Select All + Deselect All + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index e9befa5d..58c44ebc 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,5 +1,5 @@ - + + +