mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-03-19 18:10:07 +01:00
Merge pull request #644 from Merkost/migration_settings
Notes import/export moved to settings
This commit is contained in:
commit
6c7d3aa0cd
@ -1,7 +1,10 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-android-extensions'
|
||||
id 'kotlin-kapt'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
|
||||
}
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
def keystoreProperties = new Properties()
|
||||
@ -10,7 +13,7 @@ if (keystorePropertiesFile.exists()) {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.simplemobiletools.notes.pro"
|
||||
@ -70,4 +73,6 @@ dependencies {
|
||||
kapt 'androidx.room:room-compiler:2.5.1'
|
||||
implementation 'androidx.room:room-runtime:2.5.1'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.5.1'
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
||||
}
|
||||
|
24
app/proguard-rules.pro
vendored
24
app/proguard-rules.pro
vendored
@ -1,3 +1,27 @@
|
||||
-keep class com.simplemobiletools.notes.pro.models.* {
|
||||
<fields>;
|
||||
}
|
||||
|
||||
# Keep `Companion` object fields of serializable classes.
|
||||
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
|
||||
-if @kotlinx.serialization.Serializable class **
|
||||
-keepclassmembers class <1> {
|
||||
static <1>$Companion Companion;
|
||||
}
|
||||
|
||||
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
|
||||
-if @kotlinx.serialization.Serializable class ** {
|
||||
static **$* *;
|
||||
}
|
||||
-keepclassmembers class <2>$<3> {
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
|
||||
# Keep `INSTANCE.serializer()` of serializable objects.
|
||||
-if @kotlinx.serialization.Serializable class ** {
|
||||
public static ** INSTANCE;
|
||||
}
|
||||
-keepclassmembers class <1> {
|
||||
public static <1> INSTANCE;
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
|
@ -43,13 +43,11 @@ import com.simplemobiletools.notes.pro.dialogs.*
|
||||
import com.simplemobiletools.notes.pro.extensions.*
|
||||
import com.simplemobiletools.notes.pro.fragments.TextFragment
|
||||
import com.simplemobiletools.notes.pro.helpers.*
|
||||
import com.simplemobiletools.notes.pro.helpers.NotesImporter.ImportResult
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.item_checklist.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
|
||||
@ -63,11 +61,8 @@ class MainActivity : SimpleActivity() {
|
||||
private val PICK_OPEN_FILE_INTENT = 1
|
||||
private val PICK_EXPORT_FILE_INTENT = 2
|
||||
|
||||
private val PICK_IMPORT_NOTES_INTENT = 3
|
||||
private val PICK_EXPORT_NOTES_INTENT = 4
|
||||
|
||||
private lateinit var mCurrentNote: Note
|
||||
private var mNotes = ArrayList<Note>()
|
||||
private var mNotes = listOf<Note>()
|
||||
private var mAdapter: NotesPagerAdapter? = null
|
||||
private var noteViewWithTextSelected: MyEditText? = null
|
||||
private var saveNoteButton: MenuItem? = null
|
||||
@ -132,6 +127,12 @@ class MainActivity : SimpleActivity() {
|
||||
initViewPager()
|
||||
}
|
||||
|
||||
NotesHelper(this).getNotes { lastestNotes ->
|
||||
if (mNotes.size != lastestNotes.size) {
|
||||
initViewPager()
|
||||
}
|
||||
}
|
||||
|
||||
refreshMenuItems()
|
||||
pager_tab_strip.apply {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, getPercentageFontSize())
|
||||
@ -171,31 +172,29 @@ class MainActivity : SimpleActivity() {
|
||||
|
||||
main_toolbar.menu.apply {
|
||||
findItem(R.id.undo).apply {
|
||||
isVisible = showUndoButton && mCurrentNote.type == NoteType.TYPE_TEXT.value
|
||||
isVisible = showUndoButton && mCurrentNote.type == NoteType.TYPE_TEXT
|
||||
icon?.alpha = if (isEnabled) 255 else 127
|
||||
}
|
||||
|
||||
findItem(R.id.redo).apply {
|
||||
isVisible = showRedoButton && mCurrentNote.type == NoteType.TYPE_TEXT.value
|
||||
isVisible = showRedoButton && mCurrentNote.type == NoteType.TYPE_TEXT
|
||||
icon?.alpha = if (isEnabled) 255 else 127
|
||||
}
|
||||
|
||||
findItem(R.id.rename_note).isVisible = multipleNotesExist
|
||||
findItem(R.id.open_note).isVisible = multipleNotesExist
|
||||
findItem(R.id.delete_note).isVisible = multipleNotesExist
|
||||
findItem(R.id.export_all_notes).isVisible = multipleNotesExist
|
||||
findItem(R.id.open_search).isVisible = !isCurrentItemChecklist
|
||||
findItem(R.id.remove_done_items).isVisible = isCurrentItemChecklist
|
||||
findItem(R.id.sort_checklist).isVisible = isCurrentItemChecklist
|
||||
findItem(R.id.import_folder).isVisible = !isQPlus()
|
||||
findItem(R.id.import_notes).isVisible = isQPlus()
|
||||
findItem(R.id.lock_note).isVisible = mNotes.isNotEmpty() && (::mCurrentNote.isInitialized && !mCurrentNote.isLocked())
|
||||
findItem(R.id.unlock_note).isVisible = mNotes.isNotEmpty() && (::mCurrentNote.isInitialized && mCurrentNote.isLocked())
|
||||
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
|
||||
|
||||
saveNoteButton = findItem(R.id.save_note)
|
||||
saveNoteButton!!.isVisible =
|
||||
!config.autosaveNotes && showSaveButton && (::mCurrentNote.isInitialized && mCurrentNote.type == NoteType.TYPE_TEXT.value)
|
||||
!config.autosaveNotes && showSaveButton && (::mCurrentNote.isInitialized && mCurrentNote.type == NoteType.TYPE_TEXT)
|
||||
}
|
||||
|
||||
pager_tab_strip.beVisibleIf(multipleNotesExist)
|
||||
@ -223,8 +222,6 @@ class MainActivity : SimpleActivity() {
|
||||
R.id.open_file -> tryOpenFile()
|
||||
R.id.import_folder -> openFolder()
|
||||
R.id.export_as_file -> fragment?.handleUnlocking { tryExportAsFile() }
|
||||
R.id.export_all_notes -> tryExportNotes()
|
||||
R.id.import_notes -> tryImportNotes()
|
||||
R.id.print -> fragment?.handleUnlocking { printText() }
|
||||
R.id.delete_note -> fragment?.handleUnlocking { displayDeleteNotePrompt() }
|
||||
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
|
||||
@ -288,15 +285,10 @@ class MainActivity : SimpleActivity() {
|
||||
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
applicationContext.contentResolver.takePersistableUriPermission(resultData.data!!, takeFlags)
|
||||
showExportFilePickUpdateDialog(resultData.dataString!!, getCurrentNoteValue())
|
||||
} else if (requestCode == PICK_EXPORT_NOTES_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
|
||||
val outputStream = contentResolver.openOutputStream(resultData.data!!)
|
||||
exportNotesTo(outputStream)
|
||||
} else if (requestCode == PICK_IMPORT_NOTES_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
|
||||
tryImportingAsJson(resultData.data!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isCurrentItemChecklist() = if (::mCurrentNote.isInitialized) mCurrentNote.type == NoteType.TYPE_CHECKLIST.value else false
|
||||
private fun isCurrentItemChecklist() = if (::mCurrentNote.isInitialized) mCurrentNote.type == NoteType.TYPE_CHECKLIST else false
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun checkShortcuts() {
|
||||
@ -368,10 +360,10 @@ class MainActivity : SimpleActivity() {
|
||||
val file = File(realPath)
|
||||
handleUri(Uri.fromFile(file))
|
||||
} else if (intent.getBooleanExtra(NEW_TEXT_NOTE, false)) {
|
||||
val newTextNote = Note(null, getCurrentFormattedDateTime(), "", NoteType.TYPE_TEXT.value, "", PROTECTION_NONE, "")
|
||||
val newTextNote = Note(null, getCurrentFormattedDateTime(), "", NoteType.TYPE_TEXT, "", PROTECTION_NONE, "")
|
||||
addNewNote(newTextNote)
|
||||
} else if (intent.getBooleanExtra(NEW_CHECKLIST, false)) {
|
||||
val newChecklist = Note(null, getCurrentFormattedDateTime(), "", NoteType.TYPE_CHECKLIST.value, "", PROTECTION_NONE, "")
|
||||
val newChecklist = Note(null, getCurrentFormattedDateTime(), "", NoteType.TYPE_CHECKLIST, "", PROTECTION_NONE, "")
|
||||
addNewNote(newChecklist)
|
||||
} else {
|
||||
handleUri(data!!)
|
||||
@ -446,7 +438,7 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.showKeyboard || mCurrentNote.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
if (!config.showKeyboard || mCurrentNote.type == NoteType.TYPE_CHECKLIST) {
|
||||
hideKeyboard()
|
||||
}
|
||||
refreshMenuItems()
|
||||
@ -678,7 +670,7 @@ class MainActivity : SimpleActivity() {
|
||||
val checklistItems = fileText.parseChecklistItems()
|
||||
if (checklistItems != null) {
|
||||
val title = it.absolutePath.getFilenameFromPath().substringBeforeLast('.')
|
||||
val note = Note(null, title, fileText, NoteType.TYPE_CHECKLIST.value, "", PROTECTION_NONE, "")
|
||||
val note = Note(null, title, fileText, NoteType.TYPE_CHECKLIST, "", PROTECTION_NONE, "")
|
||||
runOnUiThread {
|
||||
OpenFileDialog(this, it.path) {
|
||||
displayNewNoteDialog(note.value, title = it.title, it.path, setChecklistAsDefault = true)
|
||||
@ -732,29 +724,23 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
private fun importUri(uri: Uri) {
|
||||
tryImportingAsJson(uri, force = true, showToasts = false) { success ->
|
||||
if (success) {
|
||||
return@tryImportingAsJson
|
||||
}
|
||||
|
||||
when (uri.scheme) {
|
||||
"file" -> openPath(uri.path!!)
|
||||
"content" -> {
|
||||
val realPath = getRealPathFromURI(uri)
|
||||
if (hasPermission(PERMISSION_READ_STORAGE)) {
|
||||
if (realPath != null) {
|
||||
openPath(realPath)
|
||||
} else {
|
||||
R.string.unknown_error_occurred
|
||||
}
|
||||
} else if (realPath != null && realPath != "") {
|
||||
checkFile(realPath, false) {
|
||||
addNoteFromUri(uri, realPath.getFilenameFromPath())
|
||||
}
|
||||
when (uri.scheme) {
|
||||
"file" -> openPath(uri.path!!)
|
||||
"content" -> {
|
||||
val realPath = getRealPathFromURI(uri)
|
||||
if (hasPermission(PERMISSION_READ_STORAGE)) {
|
||||
if (realPath != null) {
|
||||
openPath(realPath)
|
||||
} else {
|
||||
checkUri(uri) {
|
||||
addNoteFromUri(uri)
|
||||
}
|
||||
R.string.unknown_error_occurred
|
||||
}
|
||||
} else if (realPath != null && realPath != "") {
|
||||
checkFile(realPath, false) {
|
||||
addNoteFromUri(uri, realPath.getFilenameFromPath())
|
||||
}
|
||||
} else {
|
||||
checkUri(uri) {
|
||||
addNoteFromUri(uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -786,7 +772,7 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
val noteType = if (checklistItems != null) NoteType.TYPE_CHECKLIST.value else NoteType.TYPE_TEXT.value
|
||||
val noteType = if (checklistItems != null) NoteType.TYPE_CHECKLIST else NoteType.TYPE_TEXT
|
||||
if (!canSyncNoteWithFile) {
|
||||
val note = Note(null, noteTitle, content, noteType, "", PROTECTION_NONE, "")
|
||||
displayNewNoteDialog(note.value, title = noteTitle, "")
|
||||
@ -812,9 +798,9 @@ class MainActivity : SimpleActivity() {
|
||||
val fileText = it.readText().trim()
|
||||
val checklistItems = fileText.parseChecklistItems()
|
||||
val note = if (checklistItems != null) {
|
||||
Note(null, title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST.value, "", PROTECTION_NONE, "")
|
||||
Note(null, title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST, "", PROTECTION_NONE, "")
|
||||
} else {
|
||||
Note(null, title, "", NoteType.TYPE_TEXT.value, path, PROTECTION_NONE, "")
|
||||
Note(null, title, "", NoteType.TYPE_TEXT, path, PROTECTION_NONE, "")
|
||||
}
|
||||
|
||||
if (mNotes.any { it.title.equals(note.title, true) }) {
|
||||
@ -885,10 +871,10 @@ class MainActivity : SimpleActivity() {
|
||||
|
||||
private fun exportAsFile() {
|
||||
ExportFileDialog(this, mCurrentNote) {
|
||||
val textToExport = if (mCurrentNote.type == NoteType.TYPE_TEXT.value) getCurrentNoteText() else mCurrentNote.value
|
||||
val textToExport = if (mCurrentNote.type == NoteType.TYPE_TEXT) getCurrentNoteText() else mCurrentNote.value
|
||||
if (textToExport == null || textToExport.isEmpty()) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
} else if (mCurrentNote.type == NoteType.TYPE_TEXT.value) {
|
||||
} else if (mCurrentNote.type == NoteType.TYPE_TEXT) {
|
||||
showExportFilePickUpdateDialog(it, textToExport)
|
||||
} else {
|
||||
tryExportNoteValueToFile(it, mCurrentNote.title, textToExport, true)
|
||||
@ -896,138 +882,6 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryExportNotes() {
|
||||
if (isQPlus()) {
|
||||
hideKeyboard()
|
||||
val fileName = "${getString(R.string.notes)}_${getCurrentFormattedDateTime()}"
|
||||
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
type = EXPORT_MIME_TYPE
|
||||
putExtra(Intent.EXTRA_TITLE, fileName)
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
|
||||
try {
|
||||
startActivityForResult(this, PICK_EXPORT_NOTES_INTENT)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
toast(R.string.system_service_disabled, Toast.LENGTH_LONG)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tryExportAllNotesBelowQ()
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestUnlockNotes(callback: (unlockedNoteIds: List<Long>) -> Unit) {
|
||||
val lockedNotes = mNotes.filter { it.isLocked() }
|
||||
if (lockedNotes.isNotEmpty()) {
|
||||
runOnUiThread {
|
||||
UnlockNotesDialog(this, lockedNotes, callback)
|
||||
}
|
||||
} else {
|
||||
callback(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportNotesTo(outputStream: OutputStream?) {
|
||||
ensureBackgroundThread {
|
||||
NotesHelper(this).getNotes {
|
||||
mNotes = it
|
||||
requestUnlockNotes { unlockedNoteIds ->
|
||||
toast(R.string.exporting)
|
||||
val notesExporter = NotesExporter(this)
|
||||
notesExporter.exportNotes(mNotes, unlockedNoteIds, outputStream) { result ->
|
||||
val toastId = when (result) {
|
||||
NotesExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
else -> R.string.exporting_failed
|
||||
}
|
||||
|
||||
toast(toastId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryImportNotes() {
|
||||
hideKeyboard()
|
||||
Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = EXPORT_MIME_TYPE
|
||||
|
||||
try {
|
||||
startActivityForResult(this, PICK_IMPORT_NOTES_INTENT)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
toast(R.string.system_service_disabled, Toast.LENGTH_LONG)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryImportingAsJson(uri: Uri, force: Boolean = false, showToasts: Boolean = true, callback: ((success: Boolean) -> Unit)? = null) {
|
||||
val path: String
|
||||
val filename: String
|
||||
when (uri.scheme) {
|
||||
"file" -> {
|
||||
path = uri.path!!
|
||||
filename = path.getFilenameFromPath()
|
||||
}
|
||||
"content" -> {
|
||||
val tempFile = getTempFile("messages", "backup.txt")
|
||||
if (tempFile == null) {
|
||||
maybeToast(R.string.unknown_error_occurred, showToasts)
|
||||
callback?.invoke(false)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
filename = getFilenameFromUri(uri)
|
||||
val inputStream = contentResolver.openInputStream(uri)
|
||||
val out = FileOutputStream(tempFile)
|
||||
inputStream!!.copyTo(out)
|
||||
path = tempFile.absolutePath
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
callback?.invoke(false)
|
||||
return
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
maybeToast(R.string.invalid_file_format, showToasts)
|
||||
callback?.invoke(false)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
maybeToast(R.string.importing, showToasts)
|
||||
ensureBackgroundThread {
|
||||
NotesImporter(this).importNotes(path, filename, force) { importResult ->
|
||||
if (importResult == ImportResult.IMPORT_FAIL) {
|
||||
maybeToast(R.string.no_new_items, showToasts)
|
||||
runOnUiThread { callback?.invoke(false) }
|
||||
return@importNotes
|
||||
}
|
||||
|
||||
toast(
|
||||
when (importResult) {
|
||||
ImportResult.IMPORT_OK -> R.string.importing_successful
|
||||
ImportResult.IMPORT_PARTIAL -> R.string.importing_some_entries_failed
|
||||
else -> R.string.no_new_items
|
||||
}
|
||||
)
|
||||
initViewPager()
|
||||
runOnUiThread { callback?.invoke(true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun maybeToast(id: Int, show: Boolean) {
|
||||
if (show) {
|
||||
toast(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showExportFilePickUpdateDialog(exportPath: String, textToExport: String) {
|
||||
val items = arrayListOf(
|
||||
RadioItem(EXPORT_FILE_SYNC, getString(R.string.update_file_at_note)),
|
||||
@ -1053,73 +907,6 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryExportAllNotesBelowQ() {
|
||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||
if (it) {
|
||||
exportAllNotesBelowQ()
|
||||
} else {
|
||||
toast(R.string.no_storage_permissions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportAllNotesBelowQ() {
|
||||
ensureBackgroundThread {
|
||||
NotesHelper(this).getNotes { notes ->
|
||||
mNotes = notes
|
||||
requestUnlockNotes { unlockedNoteIds ->
|
||||
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) { any ->
|
||||
val syncFile = any as Int == EXPORT_FILE_SYNC
|
||||
var failCount = 0
|
||||
mNotes.filter { !it.isLocked() || it.id in unlockedNoteIds }.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)
|
||||
}
|
||||
|
||||
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 (index == mNotes.size - 1) {
|
||||
toast(if (failCount == 0) R.string.exporting_successful else R.string.exporting_some_entries_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryExportNoteValueToFile(path: String, title: String, content: String, showSuccessToasts: Boolean, callback: ((success: Boolean) -> Unit)? = null) {
|
||||
if (path.startsWith("content://")) {
|
||||
exportNoteValueToUri(Uri.parse(path), title, content, showSuccessToasts, callback)
|
||||
@ -1238,7 +1025,7 @@ class MainActivity : SimpleActivity() {
|
||||
private fun getCurrentNoteText() = getPagerAdapter().getCurrentNoteViewText(view_pager.currentItem)
|
||||
|
||||
private fun getCurrentNoteValue(): String {
|
||||
return if (mCurrentNote.type == NoteType.TYPE_TEXT.value) {
|
||||
return if (mCurrentNote.type == NoteType.TYPE_TEXT) {
|
||||
getCurrentNoteText() ?: ""
|
||||
} else {
|
||||
getPagerAdapter().getNoteChecklistItems(view_pager.currentItem) ?: ""
|
||||
@ -1246,7 +1033,7 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
private fun getPrintableText(): String {
|
||||
return if (mCurrentNote.type == NoteType.TYPE_TEXT.value) {
|
||||
return if (mCurrentNote.type == NoteType.TYPE_TEXT) {
|
||||
getCurrentNoteText() ?: ""
|
||||
} else {
|
||||
var printableText = ""
|
||||
@ -1261,7 +1048,7 @@ class MainActivity : SimpleActivity() {
|
||||
|
||||
private fun saveCurrentNote(force: Boolean) {
|
||||
getPagerAdapter().saveCurrentNote(view_pager.currentItem, force)
|
||||
if (mCurrentNote.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
if (mCurrentNote.type == NoteType.TYPE_CHECKLIST) {
|
||||
mCurrentNote.value = getPagerAdapter().getNoteChecklistItems(view_pager.currentItem) ?: ""
|
||||
}
|
||||
}
|
||||
@ -1359,8 +1146,8 @@ class MainActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
private fun shareText() {
|
||||
val text = if (mCurrentNote.type == NoteType.TYPE_TEXT.value) getCurrentNoteText() else mCurrentNote.value
|
||||
if (text == null || text.isEmpty()) {
|
||||
val text = if (mCurrentNote.type == NoteType.TYPE_TEXT) getCurrentNoteText() else mCurrentNote.value
|
||||
if (text.isNullOrEmpty()) {
|
||||
toast(R.string.cannot_share_empty_text)
|
||||
return
|
||||
}
|
||||
|
@ -1,25 +1,33 @@
|
||||
package com.simplemobiletools.notes.pro.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.dialogs.ExportNotesDialog
|
||||
import com.simplemobiletools.notes.pro.extensions.config
|
||||
import com.simplemobiletools.notes.pro.extensions.requestUnlockNotes
|
||||
import com.simplemobiletools.notes.pro.extensions.updateWidgets
|
||||
import com.simplemobiletools.notes.pro.extensions.widgetsDB
|
||||
import com.simplemobiletools.notes.pro.helpers.*
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.Widget
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
import java.util.*
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.util.Locale
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class SettingsActivity : SimpleActivity() {
|
||||
private val notesFileType = "application/json"
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
@ -50,6 +58,8 @@ class SettingsActivity : SimpleActivity() {
|
||||
setupCursorPlacement()
|
||||
setupIncognitoMode()
|
||||
setupCustomizeWidgetColors()
|
||||
setupNotesExport()
|
||||
setupNotesImport()
|
||||
updateTextColors(settings_nested_scrollview)
|
||||
|
||||
arrayOf(
|
||||
@ -57,7 +67,8 @@ class SettingsActivity : SimpleActivity() {
|
||||
settings_general_settings_label,
|
||||
settings_text_label,
|
||||
settings_startup_label,
|
||||
settings_saving_label
|
||||
settings_saving_label,
|
||||
settings_migrating_label,
|
||||
).forEach {
|
||||
it.setTextColor(getProperPrimaryColor())
|
||||
}
|
||||
@ -68,6 +79,26 @@ class SettingsActivity : SimpleActivity() {
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
if (uri != null) {
|
||||
toast(R.string.importing)
|
||||
importNotes(uri)
|
||||
}
|
||||
}
|
||||
|
||||
private val saveDocument = registerForActivityResult(ActivityResultContracts.CreateDocument(notesFileType)) { uri ->
|
||||
if (uri != null) {
|
||||
toast(R.string.exporting)
|
||||
NotesHelper(this).getNotes { notes ->
|
||||
requestUnlockNotes(notes) { unlockedNotes ->
|
||||
val notLockedNotes = notes.filterNot { it.isLocked() }
|
||||
val notesToExport = unlockedNotes + notLockedNotes
|
||||
exportNotes(notesToExport, uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeColors() {
|
||||
settings_color_customization_holder.setOnClickListener {
|
||||
startCustomizationActivity()
|
||||
@ -257,4 +288,63 @@ class SettingsActivity : SimpleActivity() {
|
||||
config.useIncognitoMode = settings_use_incognito_mode.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNotesExport() {
|
||||
settings_export_notes_holder.setOnClickListener {
|
||||
ExportNotesDialog(this) { filename ->
|
||||
saveDocument.launch(filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNotesImport() {
|
||||
settings_import_notes_holder.setOnClickListener {
|
||||
getContent.launch(notesFileType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportNotes(notes: List<Note>, uri: Uri) {
|
||||
if (notes.isEmpty()) {
|
||||
toast(R.string.no_entries_for_exporting)
|
||||
} else {
|
||||
try {
|
||||
val outputStream = contentResolver.openOutputStream(uri)!!
|
||||
|
||||
val jsonString = Json.encodeToString(notes)
|
||||
outputStream.use {
|
||||
it.write(jsonString.toByteArray())
|
||||
}
|
||||
toast(R.string.exporting_successful)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun importNotes(uri: Uri) {
|
||||
try {
|
||||
val jsonString = contentResolver.openInputStream(uri)!!.use { inputStream ->
|
||||
inputStream.bufferedReader().readText()
|
||||
}
|
||||
val objects = Json.decodeFromString<List<Note>>(jsonString)
|
||||
if (objects.isEmpty()) {
|
||||
toast(R.string.no_entries_for_importing)
|
||||
return
|
||||
}
|
||||
NotesHelper(this).importNotes(this, objects) { importResult ->
|
||||
when (importResult) {
|
||||
NotesHelper.ImportResult.IMPORT_OK -> toast(R.string.importing_successful)
|
||||
NotesHelper.ImportResult.IMPORT_PARTIAL -> toast(R.string.importing_some_entries_failed)
|
||||
NotesHelper.ImportResult.IMPORT_NOTHING_NEW -> toast(R.string.no_new_items)
|
||||
else -> toast(R.string.importing_failed)
|
||||
}
|
||||
}
|
||||
} catch (_: SerializationException) {
|
||||
toast(R.string.invalid_file_format)
|
||||
} catch (_: IllegalArgumentException) {
|
||||
toast(R.string.invalid_file_format)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,11 @@ import com.simplemobiletools.notes.pro.extensions.widgetsDB
|
||||
import com.simplemobiletools.notes.pro.helpers.*
|
||||
import com.simplemobiletools.notes.pro.models.ChecklistItem
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import com.simplemobiletools.notes.pro.models.Widget
|
||||
import kotlinx.android.synthetic.main.widget_config.*
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class WidgetConfigureActivity : SimpleActivity() {
|
||||
private var mBgAlpha = 0f
|
||||
@ -39,7 +42,7 @@ class WidgetConfigureActivity : SimpleActivity() {
|
||||
private var mCurrentNoteId = 0L
|
||||
private var mIsCustomizingColors = false
|
||||
private var mShowTitle = false
|
||||
private var mNotes = ArrayList<Note>()
|
||||
private var mNotes = listOf<Note>()
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
useDynamicTheme = false
|
||||
@ -156,7 +159,7 @@ class WidgetConfigureActivity : SimpleActivity() {
|
||||
mCurrentNoteId = note.id!!
|
||||
notes_picker_value.text = note.title
|
||||
text_note_view_title.text = note.title
|
||||
if (note.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
if (note.type == NoteType.TYPE_CHECKLIST) {
|
||||
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
|
||||
val items = Gson().fromJson<ArrayList<ChecklistItem>>(note.value, checklistItemType) ?: ArrayList(1)
|
||||
items.apply {
|
||||
|
@ -31,7 +31,7 @@ import kotlinx.android.synthetic.main.item_checklist.view.*
|
||||
import java.util.*
|
||||
|
||||
class ChecklistAdapter(
|
||||
activity: BaseSimpleActivity, var items: ArrayList<ChecklistItem>, val listener: ChecklistItemsListener?,
|
||||
activity: BaseSimpleActivity, var items: MutableList<ChecklistItem>, val listener: ChecklistItemsListener?,
|
||||
recyclerView: MyRecyclerView, val showIcons: Boolean, itemClick: (Any) -> Unit
|
||||
) :
|
||||
MyRecyclerViewAdapter(activity, recyclerView, itemClick), ItemTouchHelperContract {
|
||||
|
@ -10,8 +10,8 @@ import com.simplemobiletools.notes.pro.fragments.ChecklistFragment
|
||||
import com.simplemobiletools.notes.pro.fragments.NoteFragment
|
||||
import com.simplemobiletools.notes.pro.fragments.TextFragment
|
||||
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
|
||||
class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity: Activity) : FragmentStatePagerAdapter(fm) {
|
||||
private var fragments: HashMap<Int, NoteFragment> = LinkedHashMap()
|
||||
@ -30,7 +30,7 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
|
||||
return fragments[position]!!
|
||||
}
|
||||
|
||||
val fragment = if (note.type == NoteType.TYPE_TEXT.value) TextFragment() else ChecklistFragment()
|
||||
val fragment = if (note.type == NoteType.TYPE_TEXT) TextFragment() else ChecklistFragment()
|
||||
fragment.arguments = bundle
|
||||
fragments[position] = fragment
|
||||
return fragment
|
||||
|
@ -20,6 +20,9 @@ import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||
import com.simplemobiletools.notes.pro.helpers.*
|
||||
import com.simplemobiletools.notes.pro.models.ChecklistItem
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsService.RemoteViewsFactory {
|
||||
private val textIds = arrayOf(
|
||||
@ -32,7 +35,7 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
|
||||
)
|
||||
private var widgetTextColor = DEFAULT_WIDGET_TEXT_COLOR
|
||||
private var note: Note? = null
|
||||
private var checklistItems = ArrayList<ChecklistItem>()
|
||||
private var checklistItems = mutableListOf<ChecklistItem>()
|
||||
|
||||
override fun getViewAt(position: Int): RemoteViews {
|
||||
val noteId = intent.getLongExtra(NOTE_ID, 0L)
|
||||
@ -43,7 +46,7 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
|
||||
}
|
||||
|
||||
val textSize = context.getPercentageFontSize() / context.resources.displayMetrics.density
|
||||
if (note!!.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
if (note!!.type == NoteType.TYPE_CHECKLIST) {
|
||||
remoteView = RemoteViews(context.packageName, R.layout.item_checklist_widget).apply {
|
||||
val checklistItem = checklistItems.getOrNull(position) ?: return@apply
|
||||
val widgetNewTextColor = if (checklistItem.isDone) widgetTextColor.adjustAlpha(DONE_CHECKLIST_ITEM_ALPHA) else widgetTextColor
|
||||
@ -123,9 +126,8 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
|
||||
widgetTextColor = intent.getIntExtra(WIDGET_TEXT_COLOR, DEFAULT_WIDGET_TEXT_COLOR)
|
||||
val noteId = intent.getLongExtra(NOTE_ID, 0L)
|
||||
note = context.notesDB.getNoteWithId(noteId)
|
||||
if (note?.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
|
||||
checklistItems = Gson().fromJson<ArrayList<ChecklistItem>>(note!!.getNoteStoredValue(context), checklistItemType) ?: ArrayList(1)
|
||||
if (note?.type == NoteType.TYPE_CHECKLIST) {
|
||||
checklistItems = note!!.getNoteStoredValue(context)?.let { Json.decodeFromString(it) } ?: mutableListOf()
|
||||
|
||||
// checklist title can be null only because of the glitch in upgrade to 6.6.0, remove this check in the future
|
||||
checklistItems = checklistItems.filter { it.title != null }.toMutableList() as ArrayList<ChecklistItem>
|
||||
@ -135,7 +137,7 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
|
||||
override fun hasStableIds() = true
|
||||
|
||||
override fun getCount(): Int {
|
||||
return if (note?.type == NoteType.TYPE_CHECKLIST.value) {
|
||||
return if (note?.type == NoteType.TYPE_CHECKLIST) {
|
||||
checklistItems.size
|
||||
} else {
|
||||
1
|
||||
|
@ -9,10 +9,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.helpers.DEFAULT_WIDGET_TEXT_COLOR
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.interfaces.NotesDao
|
||||
import com.simplemobiletools.notes.pro.interfaces.WidgetsDao
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import com.simplemobiletools.notes.pro.models.Widget
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
@ -57,7 +57,7 @@ abstract class NotesDatabase : RoomDatabase() {
|
||||
private fun insertFirstNote(context: Context) {
|
||||
Executors.newSingleThreadScheduledExecutor().execute {
|
||||
val generalNote = context.resources.getString(R.string.general_note)
|
||||
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT.value, "", PROTECTION_NONE, "")
|
||||
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT, "", PROTECTION_NONE, "")
|
||||
db!!.NotesDao().insertOrUpdate(note)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.simplemobiletools.notes.pro.dialogs
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
||||
import kotlinx.android.synthetic.main.dialog_export_notes.view.export_notes_filename
|
||||
|
||||
class ExportNotesDialog(val activity: SimpleActivity, callback: (filename: String) -> Unit) {
|
||||
|
||||
init {
|
||||
val view = (activity.layoutInflater.inflate(R.layout.dialog_export_notes, null) as ViewGroup).apply {
|
||||
export_notes_filename.setText(
|
||||
buildString {
|
||||
append(context.getString(R.string.notes))
|
||||
append("_")
|
||||
append(context.getCurrentFormattedDateTime())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder().setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null).apply {
|
||||
activity.setupDialogStuff(view, this, R.string.export_notes) { alertDialog ->
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
|
||||
val filename = view.export_notes_filename.value
|
||||
when {
|
||||
filename.isEmpty() -> activity.toast(R.string.empty_name)
|
||||
filename.isAValidFilename() -> {
|
||||
callback(filename)
|
||||
alertDialog.dismiss()
|
||||
}
|
||||
|
||||
else -> activity.toast(R.string.invalid_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||
import com.simplemobiletools.notes.pro.extensions.parseChecklistItems
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import kotlinx.android.synthetic.main.dialog_import_folder.view.*
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import kotlinx.android.synthetic.main.dialog_import_folder.view.open_file_filename
|
||||
import kotlinx.android.synthetic.main.dialog_import_folder.view.open_file_type
|
||||
import java.io.File
|
||||
|
||||
class ImportFolderDialog(val activity: SimpleActivity, val path: String, val callback: () -> Unit) : AlertDialog.Builder(activity) {
|
||||
@ -50,21 +51,21 @@ class ImportFolderDialog(val activity: SimpleActivity, val path: String, val cal
|
||||
activity.notesDB.getNoteIdWithTitle(filename) != null -> false
|
||||
else -> true
|
||||
}
|
||||
}.forEach {
|
||||
}?.forEach {
|
||||
val storePath = if (updateFilesOnEdit) it.absolutePath else ""
|
||||
val title = it.absolutePath.getFilenameFromPath()
|
||||
val value = if (updateFilesOnEdit) "" else it.readText()
|
||||
val fileText = it.readText().trim()
|
||||
val checklistItems = fileText.parseChecklistItems()
|
||||
if (checklistItems != null) {
|
||||
saveNote(title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST.value, "")
|
||||
saveNote(title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST, "")
|
||||
} else {
|
||||
if (updateFilesOnEdit) {
|
||||
activity.handleSAFDialog(path) {
|
||||
saveNote(title, value, NoteType.TYPE_TEXT.value, storePath)
|
||||
saveNote(title, value, NoteType.TYPE_TEXT, storePath)
|
||||
}
|
||||
} else {
|
||||
saveNote(title, value, NoteType.TYPE_TEXT.value, storePath)
|
||||
saveNote(title, value, NoteType.TYPE_TEXT, storePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +76,7 @@ class ImportFolderDialog(val activity: SimpleActivity, val path: String, val cal
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveNote(title: String, value: String, type: Int, path: String) {
|
||||
private fun saveNote(title: String, value: String, type: NoteType, path: String) {
|
||||
val note = Note(null, title, value, type, path, PROTECTION_NONE, "")
|
||||
NotesHelper(activity).insertOrUpdateNote(note)
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.extensions.config
|
||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import kotlinx.android.synthetic.main.dialog_new_note.view.*
|
||||
|
||||
class NewNoteDialog(val activity: Activity, title: String? = null, val setChecklistAsDefault: Boolean, callback: (note: Note) -> Unit) {
|
||||
@ -40,12 +40,12 @@ class NewNoteDialog(val activity: Activity, title: String? = null, val setCheckl
|
||||
activity.notesDB.getNoteIdWithTitle(newTitle) != null -> activity.toast(R.string.title_taken)
|
||||
else -> {
|
||||
val type = if (view.new_note_type.checkedRadioButtonId == view.type_checklist.id) {
|
||||
NoteType.TYPE_CHECKLIST.value
|
||||
NoteType.TYPE_CHECKLIST
|
||||
} else {
|
||||
NoteType.TYPE_TEXT.value
|
||||
NoteType.TYPE_TEXT
|
||||
}
|
||||
|
||||
activity.config.lastCreatedNoteType = type
|
||||
activity.config.lastCreatedNoteType = type.value
|
||||
val newNote = Note(null, newTitle, "", type, "", PROTECTION_NONE, "")
|
||||
callback(newNote)
|
||||
alertDialog.dismiss()
|
||||
|
@ -9,8 +9,8 @@ import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
||||
import com.simplemobiletools.notes.pro.helpers.NoteType
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import kotlinx.android.synthetic.main.dialog_open_file.view.*
|
||||
import java.io.File
|
||||
|
||||
@ -47,7 +47,7 @@ class OpenFileDialog(val activity: SimpleActivity, val path: String, val callbac
|
||||
|
||||
private fun saveNote(storeContent: String, storePath: String) {
|
||||
val filename = path.getFilenameFromPath()
|
||||
val note = Note(null, filename, storeContent, NoteType.TYPE_TEXT.value, storePath, PROTECTION_NONE, "")
|
||||
val note = Note(null, filename, storeContent, NoteType.TYPE_TEXT, storePath, PROTECTION_NONE, "")
|
||||
callback(note)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class OpenNoteDialog(val activity: Activity, val callback: (checkedId: Long, new
|
||||
}
|
||||
}
|
||||
|
||||
private fun initDialog(notes: ArrayList<Note>, view: View) {
|
||||
private fun initDialog(notes: List<Note>, view: View) {
|
||||
val textColor = activity.getProperTextColor()
|
||||
notes.forEach {
|
||||
activity.layoutInflater.inflate(R.layout.open_note_item, null).apply {
|
||||
|
@ -10,7 +10,7 @@ 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, val notes: List<Note>, callback: (unlockedNoteIds: List<Long>) -> Unit) {
|
||||
class UnlockNotesDialog(val activity: BaseSimpleActivity, val notes: List<Note>, callback: (unlockedNotes: List<Note>) -> Unit) {
|
||||
private var dialog: AlertDialog? = null
|
||||
private val view = activity.layoutInflater.inflate(R.layout.dialog_unlock_notes, null) as ViewGroup
|
||||
private val redColor = activity.getColor(R.color.md_red)
|
||||
@ -29,7 +29,7 @@ class UnlockNotesDialog(val activity: BaseSimpleActivity, val notes: List<Note>,
|
||||
activity.setupDialogStuff(view, this, R.string.unlock_notes, cancelOnTouchOutside = false) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
||||
callback(unlockedNoteIds)
|
||||
callback(unlockedNoteIds.mapNotNull { id -> notes.firstOrNull { it.id == id } })
|
||||
alertDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,15 @@ import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.databases.NotesDatabase
|
||||
import com.simplemobiletools.notes.pro.dialogs.UnlockNotesDialog
|
||||
import com.simplemobiletools.notes.pro.helpers.Config
|
||||
import com.simplemobiletools.notes.pro.helpers.MyWidgetProvider
|
||||
import com.simplemobiletools.notes.pro.interfaces.NotesDao
|
||||
import com.simplemobiletools.notes.pro.interfaces.WidgetsDao
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
|
||||
val Context.config: Config get() = Config.newInstance(applicationContext)
|
||||
|
||||
@ -29,3 +32,14 @@ fun Context.updateWidgets() {
|
||||
}
|
||||
|
||||
fun Context.getPercentageFontSize() = resources.getDimension(R.dimen.middle_text_size) * (config.fontSizePercentage / 100f)
|
||||
|
||||
fun BaseSimpleActivity.requestUnlockNotes(notes: List<Note>, callback: (unlockedNotes: List<Note>) -> Unit) {
|
||||
val lockedNotes = notes.filter { it.isLocked() }
|
||||
if (lockedNotes.isNotEmpty()) {
|
||||
runOnUiThread {
|
||||
UnlockNotesDialog(this, lockedNotes, callback)
|
||||
}
|
||||
} else {
|
||||
callback(emptyList())
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
|
||||
|
||||
lateinit var view: ViewGroup
|
||||
|
||||
var items = ArrayList<ChecklistItem>()
|
||||
var items = mutableListOf<ChecklistItem>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
view = inflater.inflate(R.layout.fragment_checklist, container, false) as ViewGroup
|
||||
|
@ -5,6 +5,7 @@ import android.content.Context
|
||||
import android.os.Environment
|
||||
import android.view.Gravity
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
|
||||
class Config(context: Context) : BaseConfig(context) {
|
||||
companion object {
|
||||
|
@ -44,9 +44,6 @@ const val GRAVITY_LEFT = 0
|
||||
const val GRAVITY_CENTER = 1
|
||||
const val GRAVITY_RIGHT = 2
|
||||
|
||||
// note types
|
||||
enum class NoteType(val value: Int) { TYPE_TEXT(0), TYPE_CHECKLIST(1) }
|
||||
|
||||
// mime types
|
||||
const val MIME_TEXT_PLAIN = "text/plain"
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
package com.simplemobiletools.notes.pro.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import java.io.OutputStream
|
||||
|
||||
class NotesExporter(private val context: Context) {
|
||||
enum class ExportResult {
|
||||
EXPORT_FAIL, EXPORT_OK
|
||||
}
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
fun exportNotes(notes: List<Note>, unlockedNoteIds: List<Long>, outputStream: OutputStream?, callback: (result: ExportResult) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
if (outputStream == null) {
|
||||
callback.invoke(ExportResult.EXPORT_FAIL)
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
val writer = JsonWriter(outputStream.bufferedWriter())
|
||||
writer.use {
|
||||
try {
|
||||
var written = 0
|
||||
writer.beginArray()
|
||||
for (note in notes) {
|
||||
if (!note.isLocked() || note.id in unlockedNoteIds) {
|
||||
val noteToSave = getNoteToExport(note)
|
||||
writer.jsonValue(gson.toJson(noteToSave))
|
||||
written++
|
||||
}
|
||||
}
|
||||
writer.endArray()
|
||||
callback.invoke(ExportResult.EXPORT_OK)
|
||||
} catch (e: Exception) {
|
||||
callback.invoke(ExportResult.EXPORT_FAIL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNoteToExport(note: Note): Note {
|
||||
return Note(null, note.title, note.getNoteStoredValue(context) ?: "", note.type, "", PROTECTION_NONE, "")
|
||||
}
|
||||
}
|
@ -1,19 +1,20 @@
|
||||
package com.simplemobiletools.notes.pro.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.notes.pro.R
|
||||
import com.simplemobiletools.notes.pro.extensions.config
|
||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import com.simplemobiletools.notes.pro.models.NoteType
|
||||
import java.io.File
|
||||
|
||||
class NotesHelper(val context: Context) {
|
||||
fun getNotes(callback: (notes: ArrayList<Note>) -> Unit) {
|
||||
fun getNotes(callback: (notes: List<Note>) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
// make sure the initial note has enough time to be precreated
|
||||
if (context.config.appRunCount <= 1) {
|
||||
@ -21,8 +22,8 @@ class NotesHelper(val context: Context) {
|
||||
Thread.sleep(200)
|
||||
}
|
||||
|
||||
val notes = context.notesDB.getNotes() as ArrayList<Note>
|
||||
val notesToDelete = ArrayList<Note>(notes.size)
|
||||
val notes = context.notesDB.getNotes().toMutableList()
|
||||
val notesToDelete = mutableListOf<Note>()
|
||||
notes.forEach {
|
||||
if (it.path.isNotEmpty()) {
|
||||
if (!it.path.startsWith("content://") && !File(it.path).exists()) {
|
||||
@ -36,7 +37,7 @@ class NotesHelper(val context: Context) {
|
||||
|
||||
if (notes.isEmpty()) {
|
||||
val generalNote = context.resources.getString(R.string.general_note)
|
||||
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT.value, "", PROTECTION_NONE, "")
|
||||
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT, "", PROTECTION_NONE, "")
|
||||
context.notesDB.insertOrUpdate(note)
|
||||
notes.add(note)
|
||||
}
|
||||
@ -73,4 +74,57 @@ class NotesHelper(val context: Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun insertOrUpdateNotes(notes: List<Note>, callback: ((newNoteIds: List<Long>) -> Unit)? = null) {
|
||||
ensureBackgroundThread {
|
||||
val noteIds = context.notesDB.insertOrUpdate(notes)
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
callback?.invoke(noteIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun importNotes(activity: BaseSimpleActivity, notes: List<Note>, callback: (ImportResult) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
val currentNotes = activity.notesDB.getNotes()
|
||||
if (currentNotes.isEmpty()) {
|
||||
insertOrUpdateNotes(notes) { savedNotes ->
|
||||
|
||||
val newCurrentNotes = activity.notesDB.getNotes()
|
||||
|
||||
val result = when {
|
||||
currentNotes.size == newCurrentNotes.size -> ImportResult.IMPORT_NOTHING_NEW
|
||||
notes.size == savedNotes.size -> ImportResult.IMPORT_OK
|
||||
savedNotes.isEmpty() -> ImportResult.IMPORT_FAIL
|
||||
else -> ImportResult.IMPORT_PARTIAL
|
||||
}
|
||||
callback(result)
|
||||
}
|
||||
} else {
|
||||
var imported = 0
|
||||
var skipped = 0
|
||||
|
||||
notes.forEach { note ->
|
||||
val exists = context.notesDB.getNoteIdWithTitle(note.title) != null
|
||||
if (!exists) {
|
||||
context.notesDB.insertOrUpdate(note)
|
||||
imported++
|
||||
} else {
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
|
||||
val result = when {
|
||||
skipped == notes.size || imported == 0 -> ImportResult.IMPORT_NOTHING_NEW
|
||||
imported == notes.size -> ImportResult.IMPORT_OK
|
||||
else -> ImportResult.IMPORT_PARTIAL
|
||||
}
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class ImportResult {
|
||||
IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL, IMPORT_NOTHING_NEW
|
||||
}
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
package com.simplemobiletools.notes.pro.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||
import com.simplemobiletools.notes.pro.models.Note
|
||||
import java.io.File
|
||||
|
||||
class NotesImporter(private val context: Context) {
|
||||
enum class ImportResult {
|
||||
IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL, IMPORT_NOTHING_NEW
|
||||
}
|
||||
|
||||
private val gson = Gson()
|
||||
private var notesImported = 0
|
||||
private var notesFailed = 0
|
||||
private var notesSkipped = 0
|
||||
|
||||
fun importNotes(path: String, filename: String, force: Boolean = false, callback: (result: ImportResult) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
try {
|
||||
val inputStream = if (path.contains("/")) {
|
||||
File(path).inputStream()
|
||||
} else {
|
||||
context.assets.open(path)
|
||||
}
|
||||
|
||||
inputStream.bufferedReader().use { reader ->
|
||||
val json = reader.readText()
|
||||
val type = object : TypeToken<List<Note>>() {}.type
|
||||
val notes = gson.fromJson<List<Note>>(json, type)
|
||||
val totalNotes = notes?.size ?: 0
|
||||
if (totalNotes <= 0) {
|
||||
callback.invoke(ImportResult.IMPORT_FAIL)
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
|
||||
for (note in notes) {
|
||||
val exists = context.notesDB.getNoteIdWithTitle(note.title) != null
|
||||
if (!exists) {
|
||||
context.notesDB.insertOrUpdate(note)
|
||||
notesImported++
|
||||
} else {
|
||||
notesSkipped++
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: JsonSyntaxException) {
|
||||
if (force) {
|
||||
callback(ImportResult.IMPORT_FAIL)
|
||||
return@ensureBackgroundThread
|
||||
}
|
||||
|
||||
// Import notes expects a json with note name, content etc, but lets be more flexible and accept the basic files with note content only too
|
||||
val inputStream = if (path.contains("/")) {
|
||||
File(path).inputStream()
|
||||
} else {
|
||||
context.assets.open(path)
|
||||
}
|
||||
|
||||
inputStream.bufferedReader().use { reader ->
|
||||
val text = reader.readText()
|
||||
val note = Note(null, filename, text, NoteType.TYPE_TEXT.value, "", PROTECTION_NONE, "")
|
||||
var i = 1
|
||||
if (context.notesDB.getNoteIdWithTitle(note.title) != null) {
|
||||
while (true) {
|
||||
val tryTitle = "$filename ($i)"
|
||||
if (context.notesDB.getNoteIdWithTitle(tryTitle) == null) {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
note.title = "$filename ($i)"
|
||||
}
|
||||
|
||||
context.notesDB.insertOrUpdate(note)
|
||||
notesImported++
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
context.showErrorToast(e)
|
||||
notesFailed++
|
||||
}
|
||||
|
||||
callback.invoke(
|
||||
when {
|
||||
notesSkipped > 0 && notesImported == 0 -> ImportResult.IMPORT_NOTHING_NEW
|
||||
notesImported == 0 -> ImportResult.IMPORT_FAIL
|
||||
notesFailed > 0 -> ImportResult.IMPORT_PARTIAL
|
||||
else -> ImportResult.IMPORT_OK
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,9 @@ interface NotesDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertOrUpdate(note: Note): Long
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertOrUpdate(notes: List<Note>): List<Long>
|
||||
|
||||
@Delete
|
||||
fun deleteNote(note: Note)
|
||||
}
|
||||
|
@ -3,8 +3,16 @@ package com.simplemobiletools.notes.pro.models
|
||||
import com.simplemobiletools.commons.helpers.AlphanumericComparator
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_TITLE
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ChecklistItem(
|
||||
val id: Int,
|
||||
val dateCreated: Long = 0L,
|
||||
var title: String,
|
||||
var isDone: Boolean
|
||||
) : Comparable<ChecklistItem> {
|
||||
|
||||
data class ChecklistItem(val id: Int, val dateCreated: Long = 0L, var title: String, var isDone: Boolean) : Comparable<ChecklistItem> {
|
||||
companion object {
|
||||
var sorting = 0
|
||||
}
|
||||
|
@ -2,21 +2,27 @@ package com.simplemobiletools.notes.pro.models
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.*
|
||||
import com.simplemobiletools.commons.extensions.isBiometricIdAvailable
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_FINGERPRINT
|
||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Represents a note.
|
||||
*
|
||||
* @property value The content of the note. Could be plain text or [ChecklistItem]
|
||||
* @property type The type of the note. Should be one of the [NoteType] enum entries.
|
||||
*/
|
||||
@Serializable
|
||||
@Entity(tableName = "notes", indices = [(Index(value = ["id"], unique = true))])
|
||||
@TypeConverters(NoteTypeConverter::class)
|
||||
data class Note(
|
||||
@PrimaryKey(autoGenerate = true) var id: Long?,
|
||||
@ColumnInfo(name = "title") var title: String,
|
||||
@ColumnInfo(name = "value") var value: String,
|
||||
@ColumnInfo(name = "type") var type: Int,
|
||||
@ColumnInfo(name = "type") var type: NoteType,
|
||||
@ColumnInfo(name = "path") var path: String,
|
||||
@ColumnInfo(name = "protection_type") var protectionType: Int,
|
||||
@ColumnInfo(name = "protection_hash") var protectionHash: String
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.simplemobiletools.notes.pro.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
enum class NoteType(val value: Int) {
|
||||
TYPE_TEXT(0),
|
||||
TYPE_CHECKLIST(1);
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): NoteType {
|
||||
return values().find { it.value == value } ?: TYPE_TEXT
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.simplemobiletools.notes.pro.models
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
|
||||
class NoteTypeConverter {
|
||||
@TypeConverter
|
||||
fun fromNoteType(noteType: NoteType): Int {
|
||||
return noteType.value
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toNoteType(value: Int): NoteType {
|
||||
return NoteType.fromValue(value)
|
||||
}
|
||||
}
|
@ -346,6 +346,46 @@
|
||||
android:text="@string/display_success_message" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/settings_general_settings_divider"
|
||||
layout="@layout/divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_migrating_label"
|
||||
style="@style/SettingsSectionLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/migrating" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_export_notes_holder"
|
||||
style="@style/SettingsHolderTextViewOneLinerStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_export_notes_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/export_notes" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_import_notes_holder"
|
||||
style="@style/SettingsHolderTextViewOneLinerStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_import_notes_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/import_notes" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
34
app/src/main/res/layout/dialog_export_notes.xml
Normal file
34
app/src/main/res/layout/dialog_export_notes.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/export_notes_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/export_notes_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextInputLayout
|
||||
android:id="@+id/export_notes_filename_hint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:hint="@string/filename_without_json"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/export_notes_filename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="@dimen/bigger_text_size" />
|
||||
|
||||
</com.simplemobiletools.commons.views.MyTextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -70,18 +70,10 @@
|
||||
android:id="@+id/import_folder"
|
||||
android:title="@string/import_folder"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/import_notes"
|
||||
android:title="@string/import_notes"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/export_as_file"
|
||||
android:title="@string/export_as_file"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/export_all_notes"
|
||||
android:title="@string/export_notes"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/print"
|
||||
android:title="@string/print"
|
||||
|
Loading…
x
Reference in New Issue
Block a user