Skip to content

Commit

Permalink
fix(note-editor): restore instance state
Browse files Browse the repository at this point in the history
Now Note Editor is a fragment, it no longer receives
`android:viewHierarchyState`. This is now handled by the Activity

But, we did not need to handle this manually.
Recreating the fields, with the same `id` value restores the text

----

This fix does not handle the loss of focus for dynamic elements

During testing, this lack of focus coming back from 'Drawing'
was jarring. In Production this will have minimal impact
as the user will have lost context by the time the activity is
restored (a user will not have 'Don't keep activities' on).

Fixes 17521
  • Loading branch information
david-allison authored and lukstbit committed Dec 14, 2024
1 parent f4da4ad commit abcfcce
Showing 1 changed file with 19 additions and 46 deletions.
65 changes: 19 additions & 46 deletions AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/FieldState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package com.ichi2.anki.noteeditor
import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.core.os.BundleCompat
import com.ichi2.anki.FieldEditLine
import com.ichi2.anki.NoteEditor
import com.ichi2.anki.R
Expand All @@ -37,19 +36,20 @@ import kotlin.math.min
class FieldState private constructor(
private val editor: NoteEditor,
) {
private var savedFieldData: List<View.BaseSavedState>? = null
private var customViewIds: List<Int>? = null

fun loadFieldEditLines(type: FieldChangeType): List<FieldEditLine> {
val fieldEditLines: List<FieldEditLine>
if (type.type == Type.INIT && savedFieldData != null) {
fieldEditLines = recreateFieldsFromState()
savedFieldData = null
} else {
fieldEditLines = createFields(type)
}
for (l in fieldEditLines) {
l.id = View.generateViewId()
}
val fieldEditLines: List<FieldEditLine> =
if (type.type == Type.INIT && customViewIds != null) {
recreateFields(customViewIds!!)
} else {
createFields(type).also { fields ->
for (field in fields) {
field.id = View.generateViewId()
}
}
}

if (type.type == Type.CLEAR_KEEP_STICKY) {
// we use the UI values here as the model will post-processing steps (newline -> br).
val currentFieldStrings = editor.currentFieldStrings
Expand All @@ -69,18 +69,12 @@ class FieldState private constructor(
return fieldEditLines
}

private fun recreateFieldsFromState(): List<FieldEditLine> {
val editLines: MutableList<FieldEditLine> = ArrayList(savedFieldData!!.size)
for (state in savedFieldData!!) {
val editLineView = FieldEditLine(editor.requireContext())
if (editLineView.id == 0) {
editLineView.id = View.generateViewId()
}
editLineView.loadState(state)
editLines.add(editLineView)
}
return editLines
}
/**
* Given a list of [viewIds]: create the fields, assign the IDs and let Android
* restore the state via [FieldEditLine.onRestoreInstanceState]
*/
private fun recreateFields(viewIds: List<Int>): List<FieldEditLine> =
viewIds.map { id -> FieldEditLine(editor.requireContext()).also { field -> field.id = id } }

private fun createFields(type: FieldChangeType): List<FieldEditLine> {
val fields = getFields(type)
Expand All @@ -105,28 +99,7 @@ class FieldState private constructor(
}

fun setInstanceState(savedInstanceState: Bundle?) {
if (savedInstanceState == null) {
return
}
if (!savedInstanceState.containsKey("customViewIds") || !savedInstanceState.containsKey("android:viewHierarchyState")) {
return
}
val customViewIds = savedInstanceState.getIntegerArrayList("customViewIds")
val viewHierarchyState = savedInstanceState.getBundle("android:viewHierarchyState")
if (customViewIds == null || viewHierarchyState == null) {
return
}
val views =
BundleCompat.getSparseParcelableArray(
viewHierarchyState,
"android:views",
View.BaseSavedState::class.java,
) ?: return
val important: MutableList<View.BaseSavedState> = ArrayList(customViewIds.size)
for (i in customViewIds) {
important.add(views[i!!] as View.BaseSavedState)
}
savedFieldData = important
customViewIds = savedInstanceState?.getIntegerArrayList("customViewIds")
}

/** How fields should be changed when the UI is rebuilt */
Expand Down

0 comments on commit abcfcce

Please sign in to comment.