- wip: app crash when gson can not deserialize note

This commit is contained in:
Pavol Franek 2020-02-29 10:28:54 +01:00
parent 51f1dc67b4
commit 86714229b4
13 changed files with 65 additions and 41 deletions

View File

@ -99,8 +99,8 @@ class MainActivity : SimpleActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu, menu)
menu.apply {
findItem(R.id.undo).isVisible = showUndoButton && mCurrentNote.type == TYPE_TEXT
findItem(R.id.redo).isVisible = showRedoButton && mCurrentNote.type == TYPE_TEXT
findItem(R.id.undo).isVisible = showUndoButton && mCurrentNote.type == NoteType.TYPE_TEXT.value
findItem(R.id.redo).isVisible = showRedoButton && mCurrentNote.type == NoteType.TYPE_TEXT.value
}
updateMenuItemColors(menu)
@ -116,7 +116,7 @@ class MainActivity : SimpleActivity() {
findItem(R.id.export_all_notes).isVisible = shouldBeVisible
saveNoteButton = findItem(R.id.save_note)
saveNoteButton!!.isVisible = !config.autosaveNotes && showSaveButton && mCurrentNote.type == TYPE_TEXT
saveNoteButton!!.isVisible = !config.autosaveNotes && showSaveButton && mCurrentNote.type == NoteType.TYPE_TEXT.value
}
pager_title_strip.beVisibleIf(shouldBeVisible)
@ -274,7 +274,7 @@ class MainActivity : SimpleActivity() {
}
}
if (!config.showKeyboard || mCurrentNote.type == TYPE_CHECKLIST) {
if (!config.showKeyboard || mCurrentNote.type == NoteType.TYPE_CHECKLIST.value) {
hideKeyboard()
}
}
@ -361,7 +361,7 @@ class MainActivity : SimpleActivity() {
val fileText = it.readText().trim()
val checklistItems = fileText.parseChecklistItems()
if (checklistItems != null) {
val note = Note(null, it.absolutePath.getFilenameFromPath().substringBeforeLast('.'), fileText, TYPE_CHECKLIST)
val note = Note(null, it.absolutePath.getFilenameFromPath().substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST.value)
addNewNote(note)
} else {
runOnUiThread {
@ -416,9 +416,9 @@ class MainActivity : SimpleActivity() {
val fileText = it.readText().trim()
val checklistItems = fileText.parseChecklistItems()
val note = if (checklistItems != null) {
Note(null, title.substringBeforeLast('.'), fileText, TYPE_CHECKLIST)
Note(null, title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST.value)
} else {
Note(null, title, "", TYPE_TEXT, path)
Note(null, title, "", NoteType.TYPE_TEXT.value, path)
}
if (mNotes.any { it.title.equals(note.title, true) }) {
@ -464,10 +464,10 @@ class MainActivity : SimpleActivity() {
private fun exportAsFile() {
ExportFileDialog(this, mCurrentNote) {
val textToExport = if (mCurrentNote.type == TYPE_TEXT) getCurrentNoteText() else mCurrentNote.value
val textToExport = if (mCurrentNote.type == NoteType.TYPE_TEXT.value) getCurrentNoteText() else mCurrentNote.value
if (textToExport == null || textToExport.isEmpty()) {
toast(R.string.unknown_error_occurred)
} else if (mCurrentNote.type == TYPE_TEXT) {
} else if (mCurrentNote.type == NoteType.TYPE_TEXT.value) {
showExportFilePickUpdateDialog(it, textToExport)
} else {
tryExportNoteValueToFile(it, textToExport, true)
@ -626,7 +626,7 @@ class MainActivity : SimpleActivity() {
private fun saveCurrentNote(force: Boolean) {
getPagerAdapter().saveCurrentNote(view_pager.currentItem, force)
if (mCurrentNote.type == TYPE_CHECKLIST) {
if (mCurrentNote.type == NoteType.TYPE_CHECKLIST.value) {
mCurrentNote.value = getPagerAdapter().getNoteChecklistItems(view_pager.currentItem) ?: ""
}
}
@ -712,7 +712,7 @@ class MainActivity : SimpleActivity() {
}
private fun shareText() {
val text = if (mCurrentNote.type == TYPE_TEXT) getCurrentNoteText() else mCurrentNote.value
val text = if (mCurrentNote.type == NoteType.TYPE_TEXT.value) getCurrentNoteText() else mCurrentNote.value
if (text == null || text.isEmpty()) {
toast(R.string.cannot_share_empty_text)
return

View File

@ -122,7 +122,7 @@ class WidgetConfigureActivity : SimpleActivity() {
private fun updateCurrentNote(note: Note) {
mCurrentNoteId = note.id!!
notes_picker_value.text = note.title
if (note.type == TYPE_CHECKLIST) {
if (note.type == NoteType.TYPE_CHECKLIST.value) {
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
val items = Gson().fromJson<ArrayList<ChecklistItem>>(note.value, checklistItemType) ?: ArrayList(1)
items.apply {

View File

@ -10,7 +10,7 @@ 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.TYPE_TEXT
import com.simplemobiletools.notes.pro.helpers.NoteType
import com.simplemobiletools.notes.pro.models.Note
class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity: Activity) : FragmentStatePagerAdapter(fm) {
@ -30,7 +30,7 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
return fragments[position]!!
}
val fragment = if (note.type == TYPE_TEXT) TextFragment() else ChecklistFragment()
val fragment = if (note.type == NoteType.TYPE_TEXT.value) TextFragment() else ChecklistFragment()
fragment.arguments = bundle
fragments[position] = fragment
return fragment

View File

@ -37,7 +37,7 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
}
val textSize = context.getTextSize() / context.resources.displayMetrics.density
if (note!!.type == TYPE_CHECKLIST) {
if (note!!.type == NoteType.TYPE_CHECKLIST.value) {
remoteView = RemoteViews(context.packageName, R.layout.item_checklist_widget).apply {
val checklistItem = checklistItems.getOrNull(position) ?: return@apply
setText(checklist_title, checklistItem.title)
@ -91,7 +91,7 @@ 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 == TYPE_CHECKLIST) {
if (note?.type == NoteType.TYPE_CHECKLIST.value) {
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
checklistItems = Gson().fromJson<ArrayList<ChecklistItem>>(note!!.value, checklistItemType) ?: ArrayList(1)
if (context.config.moveUndoneChecklistItems) {
@ -103,7 +103,7 @@ class WidgetAdapter(val context: Context, val intent: Intent) : RemoteViewsServi
override fun hasStableIds() = true
override fun getCount(): Int {
return if (note?.type == TYPE_CHECKLIST) {
return if (note?.type == NoteType.TYPE_CHECKLIST.value) {
checklistItems.size
} else {
1

View File

@ -9,7 +9,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
import com.simplemobiletools.commons.helpers.DEFAULT_WIDGET_BG_COLOR
import com.simplemobiletools.notes.pro.R
import com.simplemobiletools.notes.pro.helpers.DEFAULT_WIDGET_TEXT_COLOR
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
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
@ -53,7 +53,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, "", TYPE_TEXT)
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT.value)
db!!.NotesDao().insertOrUpdate(note)
}
}

View File

@ -11,9 +11,8 @@ 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.helpers.TYPE_CHECKLIST
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
import com.simplemobiletools.notes.pro.models.Note
import kotlinx.android.synthetic.main.dialog_import_folder.view.*
import java.io.File
@ -59,14 +58,14 @@ class ImportFolderDialog(val activity: SimpleActivity, val path: String, val cal
val fileText = it.readText().trim()
val checklistItems = fileText.parseChecklistItems()
if (checklistItems != null) {
saveNote(title.substringBeforeLast('.'), fileText, TYPE_CHECKLIST, "")
saveNote(title.substringBeforeLast('.'), fileText, NoteType.TYPE_CHECKLIST.value, "")
} else {
if (updateFilesOnEdit) {
activity.handleSAFDialog(path) {
saveNote(title, value, TYPE_TEXT, storePath)
saveNote(title, value, NoteType.TYPE_TEXT.value, storePath)
}
} else {
saveNote(title, value, TYPE_TEXT, storePath)
saveNote(title, value, NoteType.TYPE_TEXT.value, storePath)
}
}
}

View File

@ -11,15 +11,14 @@ 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.TYPE_CHECKLIST
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
import com.simplemobiletools.notes.pro.helpers.NoteType
import com.simplemobiletools.notes.pro.models.Note
import kotlinx.android.synthetic.main.dialog_new_note.view.*
class NewNoteDialog(val activity: Activity, callback: (note: Note) -> Unit) {
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_new_note, null).apply {
new_note_type.check(if (activity.config.lastCreatedNoteType == TYPE_TEXT) type_text_note.id else type_checklist.id)
new_note_type.check(if (activity.config.lastCreatedNoteType == NoteType.TYPE_TEXT.value) type_text_note.id else type_checklist.id)
}
AlertDialog.Builder(activity)
@ -35,7 +34,7 @@ class NewNoteDialog(val activity: Activity, callback: (note: Note) -> Unit) {
title.isEmpty() -> activity.toast(R.string.no_title)
activity.notesDB.getNoteIdWithTitle(title) != null -> activity.toast(R.string.title_taken)
else -> {
val type = if (view.new_note_type.checkedRadioButtonId == view.type_checklist.id) TYPE_CHECKLIST else TYPE_TEXT
val type = if (view.new_note_type.checkedRadioButtonId == view.type_checklist.id) NoteType.TYPE_CHECKLIST.value else NoteType.TYPE_TEXT.value
activity.config.lastCreatedNoteType = type
val newNote = Note(null, title, "", type)
callback(newNote)

View File

@ -7,7 +7,7 @@ import com.simplemobiletools.commons.extensions.humanizePath
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.notes.pro.R
import com.simplemobiletools.notes.pro.activities.SimpleActivity
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
import com.simplemobiletools.notes.pro.helpers.NoteType
import com.simplemobiletools.notes.pro.models.Note
import kotlinx.android.synthetic.main.dialog_open_file.*
import kotlinx.android.synthetic.main.dialog_open_file.view.*
@ -45,7 +45,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, TYPE_TEXT, storePath)
val note = Note(null, filename, storeContent, NoteType.TYPE_TEXT.value, storePath)
callback(note)
dialog.dismiss()
}

View File

@ -1,6 +1,9 @@
package com.simplemobiletools.notes.pro.extensions
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.simplemobiletools.notes.pro.helpers.Config
val Fragment.config: Config? get() = if (context != null) Config.newInstance(context!!) else null
val Fragment.requiredActivity: FragmentActivity get() = this.activity!!

View File

@ -15,8 +15,10 @@ import com.simplemobiletools.notes.pro.adapters.ChecklistAdapter
import com.simplemobiletools.notes.pro.dialogs.NewChecklistItemDialog
import com.simplemobiletools.notes.pro.extensions.config
import com.simplemobiletools.notes.pro.extensions.notesDB
import com.simplemobiletools.notes.pro.extensions.requiredActivity
import com.simplemobiletools.notes.pro.extensions.updateWidgets
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
import com.simplemobiletools.notes.pro.helpers.NoteType
import com.simplemobiletools.notes.pro.helpers.NotesHelper
import com.simplemobiletools.notes.pro.interfaces.ChecklistItemsListener
import com.simplemobiletools.notes.pro.models.ChecklistItem
@ -39,17 +41,23 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
override fun onResume() {
super.onResume()
NotesHelper(activity!!).getNoteWithId(noteId) {
NotesHelper(requiredActivity).getNoteWithId(noteId) {
if (it != null && activity?.isDestroyed == false) {
note = it
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
items = Gson().fromJson<ArrayList<ChecklistItem>>(note!!.value, checklistItemType) ?: ArrayList(1)
try {
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
items = Gson().fromJson<ArrayList<ChecklistItem>>(note!!.value, checklistItemType) ?: ArrayList(1)
} catch (e: Exception) {
note?.run { migrateCheckListOnFailure(it) }
e.printStackTrace()
}
if (config!!.moveUndoneChecklistItems) {
items.sortBy { it.isDone }
}
context!!.updateTextColors(view.checklist_holder)
requiredActivity.updateTextColors(view.checklist_holder)
setupFragment()
}
}
@ -62,19 +70,35 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
}
}
private fun migrateCheckListOnFailure(note: Note) {
items.clear()
val notes = note.value.split("\n").map { it.trim() }.filter { it.isNotBlank() }
notes.forEachIndexed { index, value ->
items.add(ChecklistItem(
id = index,
title = value,
isDone = false
))
}
saveChecklist()
}
private fun setupFragment() {
val plusIcon = resources.getColoredDrawableWithColor(R.drawable.ic_plus_vector, if (context!!.isBlackAndWhiteTheme()) Color.BLACK else Color.WHITE)
val plusIcon = resources.getColoredDrawableWithColor(R.drawable.ic_plus_vector, if (requiredActivity.isBlackAndWhiteTheme()) Color.BLACK else Color.WHITE)
view.apply {
checklist_fab.apply {
setImageDrawable(plusIcon)
background.applyColorFilter(context!!.getAdjustedPrimaryColor())
background.applyColorFilter(requiredActivity.getAdjustedPrimaryColor())
setOnClickListener {
showNewItemDialog()
}
}
fragment_placeholder_2.apply {
setTextColor(context!!.getAdjustedPrimaryColor())
setTextColor(requiredActivity.getAdjustedPrimaryColor())
underlineText()
setOnClickListener {
showNewItemDialog()

View File

@ -72,7 +72,7 @@ class Config(context: Context) : BaseConfig(context) {
set(useIncognitoMode) = prefs.edit().putBoolean(USE_INCOGNITO_MODE, useIncognitoMode).apply()
var lastCreatedNoteType: Int
get() = prefs.getInt(LAST_CREATED_NOTE_TYPE, TYPE_TEXT)
get() = prefs.getInt(LAST_CREATED_NOTE_TYPE, NoteType.TYPE_TEXT.value)
set(lastCreatedNoteType) = prefs.edit().putInt(LAST_CREATED_NOTE_TYPE, lastCreatedNoteType).apply()
var moveUndoneChecklistItems: Boolean

View File

@ -37,8 +37,7 @@ const val GRAVITY_CENTER = 1
const val GRAVITY_RIGHT = 2
// note types
const val TYPE_TEXT = 0
const val TYPE_CHECKLIST = 1
enum class NoteType(val value: Int) { TYPE_TEXT(0), TYPE_CHECKLIST(1) }
// mime types
const val MIME_TEXT_PLAIN = "text/plain"

View File

@ -32,7 +32,7 @@ class NotesHelper(val context: Context) {
if (notes.isEmpty()) {
val generalNote = context.resources.getString(R.string.general_note)
val note = Note(null, generalNote, "", TYPE_TEXT)
val note = Note(null, generalNote, "", NoteType.TYPE_TEXT.value)
context.notesDB.insertOrUpdate(note)
notes.add(note)
}