Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

26.8
-----

* [**] Resolved an issue where the editor could become impossible to exit when it failed to load.

26.7
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1878,15 +1878,24 @@ class GutenbergKitActivity : BaseAppCompatActivity(), EditorImageSettingsListene
updateAndSavePostAsync(listener, isFinishing)
}

@Suppress("ReturnCount")
private fun updateFromEditor(oldContent: String, isFinishing: Boolean = false): UpdateFromEditor {
editorFragment?.let {
// Don't read title/content from a stalled editor — doing so would
// overwrite the in-memory PostModel with empty strings, and the
// postChanged observer would then persist that empty state to
// SQLite. See issue #22878.
if (!it.isEditorReady()) {
AppLog.w(AppLog.T.EDITOR, "Skipping content update: Gutenberg editor not ready")
return UpdateFromEditor.Failed(java.lang.Exception("Gutenberg editor not ready"))
}
return try {
// To reduce redundant bridge events emitted to the Gutenberg editor, we get title and content at once
val titleAndContent = it.getTitleAndContent(oldContent, isFinishing)
val title = titleAndContent.first as String
val content = titleAndContent.second as String
PostFields(title, content)
} catch (e: EditorFragmentAbstract.EditorFragmentNotAddedException) {
} catch (e: GutenbergKitEditorFragmentBase.EditorFragmentNotAddedException) {
AppLog.e(AppLog.T.EDITOR, "Impossible to save the post, we weren't able to update it.")
UpdateFromEditor.Failed(e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import org.wordpress.gutenberg.GutenbergView.TitleAndContentCallback
import org.wordpress.gutenberg.Media
import org.wordpress.gutenberg.model.EditorConfiguration
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import javax.inject.Inject

class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
Expand All @@ -51,6 +52,9 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
private var gutenbergView: GutenbergView? = null
private var isHtmlModeEnabled = false

@Volatile
private var editorReady = false

private val textWatcher = LiveTextWatcher()
private var historyChangeListener: HistoryChangeListener? = null
private var featuredImageChangeListener: FeaturedImageChangeListener? = null
Expand Down Expand Up @@ -257,7 +261,10 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
}
)

editorReady = false

gutenbergView.setEditorDidBecomeAvailable {
editorReady = true
mEditorFragmentListener.onEditorFragmentContentReady(
ArrayList<Any?>(), false
)
Expand Down Expand Up @@ -434,8 +441,19 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
)

val finalResult = try {
latch.await()
result[0]
val completed = latch.await(
GET_TITLE_AND_CONTENT_TIMEOUT_SECONDS, TimeUnit.SECONDS
)
if (!completed) {
AppLog.w(
AppLog.T.EDITOR,
"Timed out waiting for title and content from " +
"Gutenberg editor"
)
null
} else {
result[0]
}
} catch (e: InterruptedException) {
AppLog.w(
AppLog.T.EDITOR,
Expand All @@ -446,7 +464,10 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
null
}

return finalResult ?: Pair("", "")
// Surface failure to the caller as a checked exception so it can
// skip mutating the PostModel rather than persisting empty content
// over the user's existing draft. See issue #22878.
return finalResult ?: throw EditorFragmentNotAddedException()
}

override fun getEditorName(): String {
Expand Down Expand Up @@ -517,6 +538,8 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
super.onDestroy()
}

fun isEditorReady(): Boolean = editorReady

fun setXPostsEnabled(enabled: Boolean) {
isXPostsEnabled = enabled
}
Expand Down Expand Up @@ -551,6 +574,8 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
private const val CAPTURE_PHOTO_PERMISSION_REQUEST_CODE = 101
private const val CAPTURE_VIDEO_PERMISSION_REQUEST_CODE = 102

private const val GET_TITLE_AND_CONTENT_TIMEOUT_SECONDS = 5L

fun newInstance(
configuration: EditorConfiguration,
site: SiteModel
Expand Down
Loading