Skip to content

Commit dea32af

Browse files
authored
Merge pull request #806 from Crustack/feat/493
Add duplicate notes action
2 parents 4d7199b + 5a05535 commit dea32af

9 files changed

Lines changed: 104 additions & 44 deletions

File tree

TRANSLATIONS.md

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,34 @@ See [Android Translations Converter](https://github.com/Crustack/android-transla
1919
<!-- translations:start -->
2020
| Language | Coverage |
2121
|----------|----------|
22-
| 🇺🇸 English | 100% (326/326) |
23-
| 🇪🇸 Catalan | 19% (65/326) |
24-
| 🇨🇿 Czech | 96% (313/326) |
25-
| 🇩🇰 Danish | 21% (69/326) |
26-
| 🇩🇪 German | 96% (313/326) |
27-
| 🇬🇷 Greek | 22% (72/326) |
28-
| 🇪🇸 Spanish | 96% (314/326) |
29-
| 🇫🇷 French | 99% (324/326) |
30-
| 🇭🇺 Hungarian | 19% (65/326) |
31-
| 🇮🇩 Indonesian | 23% (75/326) |
32-
| 🇮🇹 Italian | 89% (291/326) |
33-
| 🇯🇵 Japanese | 22% (73/326) |
34-
| 🇲🇲 Burmese | 27% (90/326) |
35-
| 🇳🇴 Norwegian Bokmål | 32% (106/326) |
36-
| 🇳🇱 Dutch | 65% (212/326) |
37-
| 🇳🇴 Norwegian Nynorsk | 32% (106/326) |
38-
| 🇵🇱 Polish | 92% (300/326) |
39-
| 🇧🇷 Portuguese (Brazil) | 95% (312/326) |
40-
| 🇵🇹 Portuguese (Portugal) | 21% (71/326) |
41-
| 🇷🇴 Romanian | 92% (301/326) |
42-
| 🇷🇺 Russian | 93% (305/326) |
43-
| 🇸🇰 Slovak | 19% (65/326) |
44-
| 🇸🇮 Slovenian | 33% (109/326) |
45-
| 🇸🇪 Swedish | 19% (63/326) |
46-
| 🇵🇭 Tagalog | 19% (65/326) |
47-
| 🇹🇷 Turkish | 22% (73/326) |
48-
| 🇺🇦 Ukrainian | 96% (314/326) |
49-
| 🇻🇳 Vietnamese | 32% (107/326) |
50-
| 🇨🇳 Chinese (Simplified) | 96% (313/326) |
51-
| 🇹🇼 Chinese (Traditional) | 90% (294/326) |
22+
| 🇺🇸 English | 100% (328/328) |
23+
| 🇪🇸 Catalan | 19% (65/328) |
24+
| 🇨🇿 Czech | 95% (313/328) |
25+
| 🇩🇰 Danish | 21% (69/328) |
26+
| 🇩🇪 German | 95% (313/328) |
27+
| 🇬🇷 Greek | 21% (72/328) |
28+
| 🇪🇸 Spanish | 95% (314/328) |
29+
| 🇫🇷 French | 98% (324/328) |
30+
| 🇭🇺 Hungarian | 19% (65/328) |
31+
| 🇮🇩 Indonesian | 22% (75/328) |
32+
| 🇮🇹 Italian | 88% (291/328) |
33+
| 🇯🇵 Japanese | 22% (73/328) |
34+
| 🇲🇲 Burmese | 27% (90/328) |
35+
| 🇳🇴 Norwegian Bokmål | 32% (106/328) |
36+
| 🇳🇱 Dutch | 64% (212/328) |
37+
| 🇳🇴 Norwegian Nynorsk | 32% (106/328) |
38+
| 🇵🇱 Polish | 91% (300/328) |
39+
| 🇧🇷 Portuguese (Brazil) | 95% (312/328) |
40+
| 🇵🇹 Portuguese (Portugal) | 21% (71/328) |
41+
| 🇷🇴 Romanian | 91% (301/328) |
42+
| 🇷🇺 Russian | 92% (305/328) |
43+
| 🇸🇰 Slovak | 19% (65/328) |
44+
| 🇸🇮 Slovenian | 33% (109/328) |
45+
| 🇸🇪 Swedish | 19% (63/328) |
46+
| 🇵🇭 Tagalog | 19% (65/328) |
47+
| 🇹🇷 Turkish | 22% (73/328) |
48+
| 🇺🇦 Ukrainian | 95% (314/328) |
49+
| 🇻🇳 Vietnamese | 32% (107/328) |
50+
| 🇨🇳 Chinese (Simplified) | 95% (313/328) |
51+
| 🇹🇼 Chinese (Traditional) | 89% (294/328) |
5252
<!-- translations:end -->

app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,9 @@ class MainActivity : LockedActivity<ActivityMainBinding>() {
629629
val pinned = menu.addPinned(MenuItem.SHOW_AS_ACTION_ALWAYS)
630630
menu.addLabels(MenuItem.SHOW_AS_ACTION_ALWAYS)
631631
menu.addDelete(MenuItem.SHOW_AS_ACTION_ALWAYS)
632+
menu.add(R.string.duplicate, R.drawable.content_copy) {
633+
baseModel.duplicateSelectedBaseNotes()
634+
}
632635
menu.add(R.string.archive, R.drawable.archive) { moveNotes(Folder.ARCHIVED) }
633636
menu.addChangeColor()
634637
val share = menu.addShare()
@@ -645,6 +648,9 @@ class MainActivity : LockedActivity<ActivityMainBinding>() {
645648
moveNotes(Folder.NOTES)
646649
}
647650
menu.addDelete(MenuItem.SHOW_AS_ACTION_ALWAYS)
651+
menu.add(R.string.duplicate, R.drawable.content_copy) {
652+
baseModel.duplicateSelectedBaseNotes()
653+
}
648654
menu.addExportMenu(MenuItem.SHOW_AS_ACTION_ALWAYS)
649655
val pinned = menu.addPinned()
650656
menu.addLabels()

app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import com.philkes.notallyx.utils.getUriForFile
9898
import com.philkes.notallyx.utils.log
9999
import com.philkes.notallyx.utils.mergeSkipFirst
100100
import com.philkes.notallyx.utils.observeSkipFirst
101+
import com.philkes.notallyx.utils.openNote
101102
import com.philkes.notallyx.utils.shareNote
102103
import com.philkes.notallyx.utils.showColorSelectDialog
103104
import com.philkes.notallyx.utils.textMaxLengthFilter
@@ -953,6 +954,14 @@ abstract class EditActivity(private val type: Type) :
953954
}
954955
}
955956

957+
override fun duplicate() {
958+
lifecycleScope.launch {
959+
saveNote(true)
960+
val duplicateId = baseModel.duplicateNote(notallyModel.getBaseNote())
961+
openNote(duplicateId, notallyModel.type, clearBackStack = true)
962+
}
963+
}
964+
956965
override fun changeReminders() {
957966
val intent = Intent(this, RemindersActivity::class.java)
958967
intent.putExtra(RemindersActivity.NOTE_ID, notallyModel.id)

app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditNoteActivity.kt

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.philkes.notallyx.presentation.activity.note
22

3-
import android.app.Activity
43
import android.content.Intent
54
import android.graphics.Typeface
65
import android.net.Uri
@@ -53,6 +52,7 @@ import com.philkes.notallyx.presentation.view.note.action.AddNoteBottomSheet
5352
import com.philkes.notallyx.utils.LinkMovementMethod
5453
import com.philkes.notallyx.utils.copyToClipBoard
5554
import com.philkes.notallyx.utils.findAllOccurrences
55+
import com.philkes.notallyx.utils.openNote
5656
import com.philkes.notallyx.utils.wrapWithChooser
5757

5858
class EditNoteActivity : EditActivity(Type.NOTE), AddNoteActions {
@@ -486,18 +486,7 @@ class EditNoteActivity : EditActivity(Type.NOTE), AddNoteActions {
486486
}
487487

488488
private fun URLSpan.navigateToNote() {
489-
val noteId = url.getNoteIdFromUrl()
490-
val noteType = url.getNoteTypeFromUrl()
491-
when (noteType) {
492-
Type.NOTE -> goToActivity(EditNoteActivity::class.java, noteId)
493-
Type.LIST -> goToActivity(EditListActivity::class.java, noteId)
494-
}
495-
}
496-
497-
private fun goToActivity(activity: Class<out Activity>, noteId: Long) {
498-
val intent = Intent(this, activity)
499-
intent.putExtra(EXTRA_SELECTED_BASE_NOTE, noteId)
500-
startActivity(intent)
489+
openNote(this.url.getNoteIdFromUrl(), this.url.getNoteTypeFromUrl())
501490
}
502491

503492
private fun Intent?.getPickedNoteData(): Triple<String, String, Boolean> {

app/src/main/java/com/philkes/notallyx/presentation/view/note/action/MoreNoteBottomSheet.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ class MoreNoteBottomSheet(
3737
}
3838
false
3939
},
40+
Action(R.string.duplicate, R.drawable.content_copy) { _ ->
41+
callbacks.duplicate()
42+
true
43+
},
4044
Action(R.string.change_color, R.drawable.change_color) { _ ->
4145
callbacks.changeColor()
4246
true
@@ -60,6 +64,8 @@ interface MoreActions {
6064

6165
fun changeColor()
6266

67+
fun duplicate()
68+
6369
fun changeReminders()
6470

6571
fun changeLabels()

app/src/main/java/com/philkes/notallyx/presentation/viewmodel/BaseNoteModel.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import com.philkes.notallyx.data.model.Header
4040
import com.philkes.notallyx.data.model.Item
4141
import com.philkes.notallyx.data.model.Label
4242
import com.philkes.notallyx.data.model.SearchResult
43+
import com.philkes.notallyx.data.model.deepCopy
4344
import com.philkes.notallyx.data.model.toNoteIdReminders
4445
import com.philkes.notallyx.presentation.activity.main.fragment.settings.SettingsFragment.Companion.EXTRA_SHOW_IMPORT_BACKUPS_FOLDER
4546
import com.philkes.notallyx.presentation.getQuantityString
@@ -93,7 +94,6 @@ import com.philkes.notallyx.utils.viewFile
9394
import java.io.File
9495
import java.util.concurrent.atomic.AtomicInteger
9596
import javax.crypto.Cipher
96-
import kotlin.collections.map
9797
import kotlinx.coroutines.CoroutineExceptionHandler
9898
import kotlinx.coroutines.Dispatchers
9999
import kotlinx.coroutines.launch
@@ -701,6 +701,37 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
701701
}
702702
}
703703

704+
suspend fun duplicateNote(note: BaseNote) = duplicateNotes(listOf(note)).first()
705+
706+
suspend fun duplicateNotes(notes: Collection<BaseNote>): List<Long> {
707+
val now = System.currentTimeMillis()
708+
val copies: List<BaseNote> =
709+
notes.map { original ->
710+
original
711+
.deepCopy()
712+
.copy(
713+
id = 0L,
714+
title =
715+
if (original.title.isNotEmpty())
716+
"${original.title} (${app.getString(R.string.copy)})"
717+
else app.getString(R.string.copy),
718+
timestamp = now,
719+
modifiedTimestamp = now,
720+
)
721+
}
722+
return withContext(Dispatchers.IO) { baseNoteDao.insert(copies) }
723+
}
724+
725+
fun duplicateSelectedBaseNotes() {
726+
if (actionMode.isEmpty()) return
727+
val selected = actionMode.selectedNotes.values.toList()
728+
viewModelScope.launch {
729+
duplicateNotes(selected)
730+
actionMode.close(true)
731+
app.showToast(app.getQuantityString(R.plurals.duplicated_notes, selected.size))
732+
}
733+
}
734+
704735
suspend fun getAllLabels() = withContext(Dispatchers.IO) { labelDao.getArrayOfAll() }
705736

706737
fun deleteLabel(value: String) {

app/src/main/java/com/philkes/notallyx/utils/AndroidExtensions.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ fun Fragment.showErrorDialog(
208208
.show()
209209
}
210210

211+
fun Activity.openNote(noteId: Long, noteType: Type, clearBackStack: Boolean = false) {
212+
val activity =
213+
when (noteType) {
214+
Type.NOTE -> EditNoteActivity::class.java
215+
Type.LIST -> EditListActivity::class.java
216+
}
217+
val intent = Intent(this, activity)
218+
if (clearBackStack) {
219+
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
220+
}
221+
intent.putExtra(EXTRA_SELECTED_BASE_NOTE, noteId)
222+
startActivity(intent)
223+
}
224+
211225
fun Activity.showErrorDialog(
212226
throwable: Throwable,
213227
titleResId: Int,

app/src/main/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
<string name="documentation">Documentation</string>
140140
<string name="donate">Make a Donation</string>
141141
<string name="drag_handle">Drag Handle</string>
142+
<string name="duplicate">Duplicate</string>
143+
<plurals name="duplicated_notes">
144+
<item quantity="one">Duplicated %1$d note</item>
145+
<item quantity="other">Duplicated %1$d notes</item>
146+
</plurals>
142147
<string name="edit">Edit</string>
143148
<string name="edit_color">Edit Color</string>
144149
<string name="edit_label">Edit label</string>

app/translations.xlsx

2 KB
Binary file not shown.

0 commit comments

Comments
 (0)