Skip to content

Commit 7b12650

Browse files
author
Pavol Franek
committed
- fixed app crash when gson can not deserialize note
- create checklist notes if user paste note with new line char
1 parent 8671422 commit 7b12650

File tree

4 files changed

+75
-68
lines changed

4 files changed

+75
-68
lines changed

app/src/main/kotlin/com/simplemobiletools/notes/pro/adapters/NotesPagerAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
5959

6060
fun saveAllFragmentTexts() = fragments.values.forEach { (it as? TextFragment)?.saveText(false) }
6161

62-
fun getNoteChecklistItems(position: Int) = (fragments[position] as? ChecklistFragment)?.getChecklistItems()
62+
fun getNoteChecklistItems(position: Int) = (fragments[position] as? ChecklistFragment)?.checklistItems
6363

6464
fun undo(position: Int) = (fragments[position] as? TextFragment)?.undo()
6565

app/src/main/kotlin/com/simplemobiletools/notes/pro/extensions/Fragment.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package com.simplemobiletools.notes.pro.extensions
22

33
import androidx.fragment.app.Fragment
44
import androidx.fragment.app.FragmentActivity
5+
import com.simplemobiletools.notes.pro.BuildConfig
56
import com.simplemobiletools.notes.pro.helpers.Config
67

78
val Fragment.config: Config? get() = if (context != null) Config.newInstance(context!!) else null
89

910
val Fragment.requiredActivity: FragmentActivity get() = this.activity!!
11+
12+
val Fragment.isDebug get(): Boolean = BuildConfig.DEBUG

app/src/main/kotlin/com/simplemobiletools/notes/pro/fragments/ChecklistFragment.kt

Lines changed: 64 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,69 +13,66 @@ import com.simplemobiletools.notes.pro.R
1313
import com.simplemobiletools.notes.pro.activities.SimpleActivity
1414
import com.simplemobiletools.notes.pro.adapters.ChecklistAdapter
1515
import com.simplemobiletools.notes.pro.dialogs.NewChecklistItemDialog
16-
import com.simplemobiletools.notes.pro.extensions.config
17-
import com.simplemobiletools.notes.pro.extensions.notesDB
18-
import com.simplemobiletools.notes.pro.extensions.requiredActivity
19-
import com.simplemobiletools.notes.pro.extensions.updateWidgets
16+
import com.simplemobiletools.notes.pro.extensions.*
2017
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
21-
import com.simplemobiletools.notes.pro.helpers.NoteType
2218
import com.simplemobiletools.notes.pro.helpers.NotesHelper
2319
import com.simplemobiletools.notes.pro.interfaces.ChecklistItemsListener
2420
import com.simplemobiletools.notes.pro.models.ChecklistItem
2521
import com.simplemobiletools.notes.pro.models.Note
2622
import kotlinx.android.synthetic.main.fragment_checklist.view.*
2723

2824
class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
29-
private var noteId = 0L
25+
26+
private var noteId = 0L
27+
private var items = ArrayList<ChecklistItem>()
3028
private var note: Note? = null
31-
private var items = ArrayList<ChecklistItem>()
3229

3330
lateinit var view: ViewGroup
3431

32+
val checklistItems get(): String = Gson().toJson(items)
33+
3534
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
36-
view = inflater.inflate(R.layout.fragment_checklist, container, false) as ViewGroup
35+
view = inflater.inflate(R.layout.fragment_checklist, container, false) as ViewGroup
3736
noteId = arguments!!.getLong(NOTE_ID, 0L)
3837
return view
3938
}
4039

4140
override fun onResume() {
4241
super.onResume()
4342

44-
NotesHelper(requiredActivity).getNoteWithId(noteId) {
45-
if (it != null && activity?.isDestroyed == false) {
46-
note = it
43+
loadNoteById(noteId)
44+
}
45+
46+
override fun setMenuVisibility(menuVisible: Boolean) {
47+
super.setMenuVisibility(menuVisible)
48+
49+
if (menuVisible) activity?.hideKeyboard()
50+
}
51+
52+
private fun loadNoteById(noteId: Long) {
53+
NotesHelper(requiredActivity).getNoteWithId(noteId) { storedNote ->
54+
if (storedNote != null && activity?.isDestroyed == false) {
55+
note = storedNote
4756

4857
try {
49-
val checklistItemType = object : TypeToken<List<ChecklistItem>>() {}.type
50-
items = Gson().fromJson<ArrayList<ChecklistItem>>(note!!.value, checklistItemType) ?: ArrayList(1)
58+
val checklistItemType = object: TypeToken<List<ChecklistItem>>(){}.type
59+
items = Gson().fromJson<ArrayList<ChecklistItem>>(storedNote.value, checklistItemType) ?: ArrayList(1)
5160
} catch (e: Exception) {
52-
note?.run { migrateCheckListOnFailure(it) }
53-
e.printStackTrace()
54-
}
55-
56-
if (config!!.moveUndoneChecklistItems) {
57-
items.sortBy { it.isDone }
61+
migrateCheckListOnFailure(storedNote)
62+
if (isDebug) e.printStackTrace()
5863
}
5964

65+
if (config?.moveUndoneChecklistItems == true) items.sortBy { it.isDone }
6066
requiredActivity.updateTextColors(view.checklist_holder)
6167
setupFragment()
6268
}
6369
}
6470
}
6571

66-
override fun setMenuVisibility(menuVisible: Boolean) {
67-
super.setMenuVisibility(menuVisible)
68-
if (menuVisible) {
69-
activity?.hideKeyboard()
70-
}
71-
}
72-
7372
private fun migrateCheckListOnFailure(note: Note) {
7473
items.clear()
7574

76-
val notes = note.value.split("\n").map { it.trim() }.filter { it.isNotBlank() }
77-
78-
notes.forEachIndexed { index, value ->
75+
note.value.split("\n").map { it.trim() }.filter { it.isNotBlank() }.forEachIndexed { index, value ->
7976
items.add(ChecklistItem(
8077
id = index,
8178
title = value,
@@ -88,53 +85,63 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
8885

8986
private fun setupFragment() {
9087
val plusIcon = resources.getColoredDrawableWithColor(R.drawable.ic_plus_vector, if (requiredActivity.isBlackAndWhiteTheme()) Color.BLACK else Color.WHITE)
88+
9189
view.apply {
92-
checklist_fab.apply {
90+
with(checklist_fab) {
9391
setImageDrawable(plusIcon)
9492
background.applyColorFilter(requiredActivity.getAdjustedPrimaryColor())
9593
setOnClickListener {
9694
showNewItemDialog()
9795
}
9896
}
9997

100-
fragment_placeholder_2.apply {
98+
with(fragment_placeholder_2) {
10199
setTextColor(requiredActivity.getAdjustedPrimaryColor())
102100
underlineText()
103101
setOnClickListener {
104102
showNewItemDialog()
105103
}
106104
}
107105
}
106+
108107
setupAdapter()
109108
}
110109

111110
private fun showNewItemDialog() {
112-
NewChecklistItemDialog(activity as SimpleActivity) {
113-
var currentMaxId = items.maxBy { it.id }?.id ?: 0
114-
it.forEach {
115-
val checklistItem = ChecklistItem(currentMaxId + 1, it, false)
116-
items.add(checklistItem)
117-
currentMaxId++
111+
NewChecklistItemDialog(activity as SimpleActivity) { titles ->
112+
var currentMaxId = items.maxBy { item -> item.id }?.id ?: 0
113+
114+
titles.forEach { title ->
115+
title.split("\n").map { it.trim() }.filter { it.isNotBlank() }.forEach { row ->
116+
items.add(ChecklistItem(currentMaxId + 1, row, false))
117+
currentMaxId++
118+
}
118119
}
120+
119121
saveNote()
120-
if (items.size == it.size) {
121-
setupAdapter()
122-
} else {
123-
(view.checklist_list.adapter as? ChecklistAdapter)?.notifyDataSetChanged()
124-
}
122+
setupAdapter()
123+
124+
(view.checklist_list.adapter as? ChecklistAdapter)?.notifyDataSetChanged()
125125
}
126126
}
127127

128128
private fun setupAdapter() {
129-
view.apply {
129+
with(view) {
130130
fragment_placeholder.beVisibleIf(items.isEmpty())
131131
fragment_placeholder_2.beVisibleIf(items.isEmpty())
132132
checklist_list.beVisibleIf(items.isNotEmpty())
133133
}
134134

135-
ChecklistAdapter(activity as SimpleActivity, items, this, view.checklist_list, true) {
136-
val clickedNote = it as ChecklistItem
135+
ChecklistAdapter(
136+
activity = activity as SimpleActivity,
137+
items = items,
138+
listener = this,
139+
recyclerView = view.checklist_list,
140+
showIcons = true
141+
) { item ->
142+
val clickedNote = item as ChecklistItem
137143
clickedNote.isDone = !clickedNote.isDone
144+
138145
saveNote(items.indexOfFirst { it.id == clickedNote.id })
139146
context?.updateWidgets()
140147
}.apply {
@@ -144,27 +151,22 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
144151

145152
private fun saveNote(refreshIndex: Int = -1) {
146153
ensureBackgroundThread {
147-
if (note != null && context != null) {
148-
if (refreshIndex != -1) {
149-
view.checklist_list.post {
150-
view.checklist_list.adapter?.notifyItemChanged(refreshIndex)
154+
context?.let { ctx ->
155+
note?.let { currentNote ->
156+
if (refreshIndex != -1) {
157+
view.checklist_list.post {
158+
view.checklist_list.adapter?.notifyItemChanged(refreshIndex)
159+
}
151160
}
152-
}
153161

154-
note!!.value = getChecklistItems()
155-
context?.notesDB?.insertOrUpdate(note!!)
156-
context?.updateWidgets()
162+
currentNote.value = checklistItems
163+
ctx.notesDB.insertOrUpdate(currentNote)
164+
ctx.updateWidgets()
165+
}
157166
}
158167
}
159168
}
160169

161-
fun getChecklistItems() = Gson().toJson(items)
162-
163-
override fun saveChecklist() {
164-
saveNote()
165-
}
166-
167-
override fun refreshItems() {
168-
setupAdapter()
169-
}
170+
override fun saveChecklist() { saveNote() }
171+
override fun refreshItems() { setupAdapter() }
170172
}

app/src/main/res/layout/dialog_new_checklist_item.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<LinearLayout
3-
xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
43
android:id="@+id/dialog_holder"
54
android:layout_width="match_parent"
65
android:layout_height="match_parent"
@@ -15,25 +14,28 @@
1514
android:layout_height="wrap_content"
1615
android:layout_marginBottom="@dimen/medium_margin"
1716
android:inputType="textCapSentences"
17+
android:maxLength="500"
1818
android:textCursorDrawable="@null"
19-
android:textSize="@dimen/normal_text_size"/>
19+
android:textSize="@dimen/normal_text_size" />
2020

2121
<com.simplemobiletools.commons.views.MyEditText
2222
android:id="@+id/checklist_item_title_2"
2323
android:layout_width="match_parent"
2424
android:layout_height="wrap_content"
2525
android:layout_marginBottom="@dimen/medium_margin"
2626
android:inputType="textCapSentences"
27+
android:maxLength="500"
2728
android:textCursorDrawable="@null"
28-
android:textSize="@dimen/normal_text_size"/>
29+
android:textSize="@dimen/normal_text_size" />
2930

3031
<com.simplemobiletools.commons.views.MyEditText
3132
android:id="@+id/checklist_item_title_3"
3233
android:layout_width="match_parent"
3334
android:layout_height="wrap_content"
3435
android:layout_marginBottom="@dimen/medium_margin"
3536
android:inputType="textCapSentences"
37+
android:maxLength="500"
3638
android:textCursorDrawable="@null"
37-
android:textSize="@dimen/normal_text_size"/>
39+
android:textSize="@dimen/normal_text_size" />
3840

3941
</LinearLayout>

0 commit comments

Comments
 (0)