mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-03-19 18:10:07 +01:00
Allow exporting locked notes
This commit is contained in:
parent
f1bbad2c9c
commit
0bc818245c
@ -904,17 +904,24 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportNotesTo(outputStream: OutputStream?) {
|
||||
toast(R.string.exporting)
|
||||
ensureBackgroundThread {
|
||||
val notesExporter = NotesExporter(this)
|
||||
notesExporter.exportNotes(outputStream) {
|
||||
val toastId = when (it) {
|
||||
NotesExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
else -> R.string.exporting_failed
|
||||
}
|
||||
private fun requestUnlockNotes(callback: (List<Long>) -> Unit) {
|
||||
val lockedNotes = mNotes.filter { it.isLocked() }
|
||||
UnlockNotesDialog(this, lockedNotes, callback)
|
||||
}
|
||||
|
||||
toast(toastId)
|
||||
private fun exportNotesTo(outputStream: OutputStream?) {
|
||||
requestUnlockNotes { unlockedIds ->
|
||||
toast(R.string.exporting)
|
||||
ensureBackgroundThread {
|
||||
val notesExporter = NotesExporter(this)
|
||||
notesExporter.exportNotes(outputStream, unlockedIds) {
|
||||
val toastId = when (it) {
|
||||
NotesExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
else -> R.string.exporting_failed
|
||||
}
|
||||
|
||||
toast(toastId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1011,49 +1018,51 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
private fun exportAllNotesBelowQ() {
|
||||
ExportFilesDialog(this, mNotes) { parent, extension ->
|
||||
val items = arrayListOf(
|
||||
RadioItem(EXPORT_FILE_SYNC, getString(R.string.update_file_at_note)),
|
||||
RadioItem(EXPORT_FILE_NO_SYNC, getString(R.string.only_export_file_content))
|
||||
)
|
||||
requestUnlockNotes { unlockedIds ->
|
||||
ExportFilesDialog(this, mNotes) { parent, extension ->
|
||||
val items = arrayListOf(
|
||||
RadioItem(EXPORT_FILE_SYNC, getString(R.string.update_file_at_note)),
|
||||
RadioItem(EXPORT_FILE_NO_SYNC, getString(R.string.only_export_file_content))
|
||||
)
|
||||
|
||||
RadioGroupDialog(this, items) {
|
||||
val syncFile = it as Int == EXPORT_FILE_SYNC
|
||||
var failCount = 0
|
||||
NotesHelper(this).getNotes {
|
||||
mNotes = it
|
||||
mNotes.filter { !it.isLocked() }.forEachIndexed { index, note ->
|
||||
val filename = if (extension.isEmpty()) note.title else "${note.title}.$extension"
|
||||
val file = File(parent, filename)
|
||||
if (!filename.isAValidFilename()) {
|
||||
toast(String.format(getString(R.string.filename_invalid_characters_placeholder, filename)))
|
||||
} else {
|
||||
val noteStoredValue = note.getNoteStoredValue(this) ?: ""
|
||||
tryExportNoteValueToFile(file.absolutePath, mCurrentNote.title, note.value, false) { exportedSuccessfully ->
|
||||
if (exportedSuccessfully) {
|
||||
if (syncFile) {
|
||||
note.path = file.absolutePath
|
||||
note.value = ""
|
||||
} else {
|
||||
note.path = ""
|
||||
note.value = noteStoredValue
|
||||
RadioGroupDialog(this, items) { any ->
|
||||
val syncFile = any as Int == EXPORT_FILE_SYNC
|
||||
var failCount = 0
|
||||
NotesHelper(this).getNotes { notes ->
|
||||
mNotes = notes
|
||||
mNotes.filter { !it.isLocked() || it.id in unlockedIds }.forEachIndexed { index, note ->
|
||||
val filename = if (extension.isEmpty()) note.title else "${note.title}.$extension"
|
||||
val file = File(parent, filename)
|
||||
if (!filename.isAValidFilename()) {
|
||||
toast(String.format(getString(R.string.filename_invalid_characters_placeholder, filename)))
|
||||
} else {
|
||||
val noteStoredValue = note.getNoteStoredValue(this) ?: ""
|
||||
tryExportNoteValueToFile(file.absolutePath, mCurrentNote.title, note.value, false) { exportedSuccessfully ->
|
||||
if (exportedSuccessfully) {
|
||||
if (syncFile) {
|
||||
note.path = file.absolutePath
|
||||
note.value = ""
|
||||
} else {
|
||||
note.path = ""
|
||||
note.value = noteStoredValue
|
||||
}
|
||||
|
||||
NotesHelper(this).insertOrUpdateNote(note)
|
||||
}
|
||||
|
||||
NotesHelper(this).insertOrUpdateNote(note)
|
||||
}
|
||||
if (mCurrentNote.id == note.id) {
|
||||
mCurrentNote.value = note.value
|
||||
mCurrentNote.path = note.path
|
||||
getPagerAdapter().updateCurrentNoteData(view_pager.currentItem, mCurrentNote.path, mCurrentNote.value)
|
||||
}
|
||||
|
||||
if (mCurrentNote.id == note.id) {
|
||||
mCurrentNote.value = note.value
|
||||
mCurrentNote.path = note.path
|
||||
getPagerAdapter().updateCurrentNoteData(view_pager.currentItem, mCurrentNote.path, mCurrentNote.value)
|
||||
}
|
||||
if (!exportedSuccessfully) {
|
||||
failCount++
|
||||
}
|
||||
|
||||
if (!exportedSuccessfully) {
|
||||
failCount++
|
||||
}
|
||||
|
||||
if (index == mNotes.size - 1) {
|
||||
toast(if (failCount == 0) R.string.exporting_successful else R.string.exporting_some_entries_failed)
|
||||
if (index == mNotes.size - 1) {
|
||||
toast(if (failCount == 0) R.string.exporting_successful else R.string.exporting_some_entries_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,16 +24,16 @@ class NewNoteDialog(val activity: Activity, title: String? = null, val setCheckl
|
||||
new_note_type.check(defaultType)
|
||||
}
|
||||
|
||||
view.note_title.setText(title)
|
||||
view.locked_note_title.setText(title)
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this, R.string.new_note) { alertDialog ->
|
||||
alertDialog.showKeyboard(view.note_title)
|
||||
alertDialog.showKeyboard(view.locked_note_title)
|
||||
alertDialog.getButton(BUTTON_POSITIVE).setOnClickListener {
|
||||
val newTitle = view.note_title.value
|
||||
val newTitle = view.locked_note_title.value
|
||||
ensureBackgroundThread {
|
||||
when {
|
||||
newTitle.isEmpty() -> activity.toast(R.string.no_title)
|
||||
|
@ -18,16 +18,16 @@ class RenameNoteDialog(val activity: SimpleActivity, val note: Note, val current
|
||||
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_note, null)
|
||||
view.note_title.setText(note.title)
|
||||
view.locked_note_title.setText(note.title)
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this, R.string.rename_note) { alertDialog ->
|
||||
alertDialog.showKeyboard(view.note_title)
|
||||
alertDialog.showKeyboard(view.locked_note_title)
|
||||
alertDialog.getButton(BUTTON_POSITIVE).setOnClickListener {
|
||||
val title = view.note_title.value
|
||||
val title = view.locked_note_title.value
|
||||
ensureBackgroundThread {
|
||||
newTitleConfirmed(title, alertDialog)
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.simplemobiletools.notes.pro.dialogs
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import kotlinx.android.synthetic.main.dialog_unlock_notes.view.*
|
||||
import kotlinx.android.synthetic.main.item_locked_note.view.*
|
||||
|
||||
class UnlockNotesDialog(val activity: BaseSimpleActivity, notes: List<Note>, callback: (unlockedNoteIds: List<Long>) -> Unit) {
|
||||
private val view = activity.layoutInflater.inflate(R.layout.dialog_unlock_notes, null) as ViewGroup
|
||||
private val redColor = activity.getColor(R.color.md_red)
|
||||
private val greenColor = activity.getColor(R.color.md_green)
|
||||
private val unlockedNoteIds = mutableListOf<Long>()
|
||||
|
||||
init {
|
||||
for (note in notes) {
|
||||
addLockedNoteView(note)
|
||||
}
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this, R.string.unlock_notes, cancelOnTouchOutside = false) { alertDialog ->
|
||||
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
||||
callback(unlockedNoteIds)
|
||||
alertDialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addLockedNoteView(note: Note) {
|
||||
activity.layoutInflater.inflate(R.layout.item_locked_note, null).apply {
|
||||
view.notes_holder.addView(this)
|
||||
activity.updateTextColors(view.notes_holder)
|
||||
locked_note_title.text = note.title
|
||||
locked_unlocked_image.applyColorFilter(redColor)
|
||||
locked_note_holder.setOnClickListener {
|
||||
if (note.id !in unlockedNoteIds) {
|
||||
activity.performSecurityCheck(
|
||||
protectionType = note.protectionType,
|
||||
requiredHash = note.protectionHash,
|
||||
successCallback = { _, _ ->
|
||||
unlockedNoteIds.add(note.id!!)
|
||||
locked_unlocked_image.apply {
|
||||
setImageResource(R.drawable.ic_lock_open_vector)
|
||||
applyColorFilter(greenColor)
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
unlockedNoteIds.remove(note.id)
|
||||
locked_unlocked_image.apply {
|
||||
setImageResource(R.drawable.ic_lock_vector)
|
||||
applyColorFilter(redColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ class NotesExporter(private val context: Context) {
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
fun exportNotes(outputStream: OutputStream?, callback: (result: ExportResult) -> Unit) {
|
||||
fun exportNotes(outputStream: OutputStream?, unlockedNoteIds: List<Long>, callback: (result: ExportResult) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
if (outputStream == null) {
|
||||
callback.invoke(ExportResult.EXPORT_FAIL)
|
||||
@ -29,7 +29,7 @@ class NotesExporter(private val context: Context) {
|
||||
writer.beginArray()
|
||||
val notes = context.notesDB.getNotes() as ArrayList<Note>
|
||||
for (note in notes) {
|
||||
if (note.protectionType == PROTECTION_NONE) {
|
||||
if (!note.isLocked() || note.id in unlockedNoteIds) {
|
||||
val noteToSave = getNoteToExport(note)
|
||||
writer.jsonValue(gson.toJson(noteToSave))
|
||||
written++
|
||||
|
3
app/src/main/res/drawable/ic_lock_open_vector.xml
Normal file
3
app/src/main/res/drawable/ic_lock_open_vector.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12 17c1.1 0 2-0.9 2-2s-0.9-2-2-2-2 0.9-2 2 0.9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 0.9-2 2v10c0 1.1 0.9 2 2 2h12c1.1 0 2-0.9 2-2V10c0-1.1-0.9-2-2-2zm0 12H6V10h12v10z"/>
|
||||
</vector>
|
@ -17,7 +17,7 @@
|
||||
android:hint="@string/label">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/note_title"
|
||||
android:id="@+id/locked_note_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapSentences"
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:hint="@string/title">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/note_title"
|
||||
android:id="@+id/locked_note_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapSentences"
|
||||
|
30
app/src/main/res/layout/dialog_unlock_notes.xml
Normal file
30
app/src/main/res/layout/dialog_unlock_notes.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/found_locked_notes_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/big_margin"
|
||||
android:layout_marginTop="@dimen/small_margin"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:text="@string/found_locked_notes_info" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/notes_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
35
app/src/main/res/layout/item_locked_note.xml
Normal file
35
app/src/main/res/layout/item_locked_note.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/locked_note_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ripple_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:paddingHorizontal="@dimen/normal_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/locked_note_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/locked_unlocked_image"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Passwords" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/locked_unlocked_image"
|
||||
android:layout_width="@dimen/fab_size"
|
||||
android:layout_height="@dimen/fab_size"
|
||||
android:paddingVertical="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_lock_vector"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user