Skip to content

Commit 0203851

Browse files
authored
feat: Implement LatestContentProvider for WebView recovery (#22774)
* feat: Send GutenbergKit the latest content when requested Allow GutenbergKit to retrieve the latest content persisted in the host app as needed. This is important for allowing GutenbergKit to display the latest content after the WebView reloads or re-initializes from memory pressure or backgrounding. * feat: Set GutenbergKit post status * build: Update GutenbergKit version Integrate an unrelated content loss fix that is necessary for testing this branch's focus on content preservation.
1 parent 6cfa2a2 commit 0203851

7 files changed

Lines changed: 67 additions & 8 deletions

File tree

WordPress/src/main/java/org/wordpress/android/ui/posts/EditorConfigurationBuilder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ object EditorConfigurationBuilder {
2727
setTitle(settings.getSetting<String>("postTitle") ?: "")
2828
setContent(settings.getSetting<String>("postContent") ?: "")
2929
setPostId(postId)
30+
setPostStatus(settings.getSetting<String>("status") ?: "draft")
3031

3132
setSiteApiNamespace(siteApiNamespace)
3233
setNamespaceExcludedPaths(

WordPress/src/main/java/org/wordpress/android/ui/posts/GutenbergKitActivity.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,10 @@ class GutenbergKitActivity : BaseAppCompatActivity(), EditorImageSettingsListene
29502950
Handler(Looper.getMainLooper()).post { invalidateOptionsMenu() }
29512951
}
29522952

2953+
override fun getPersistedTitle(): String = editPostRepository.title
2954+
2955+
override fun getPersistedContent(): String = editPostRepository.content
2956+
29532957
// FluxC events
29542958
@Suppress("unused", "CyclomaticComplexMethod")
29552959
@Subscribe(threadMode = ThreadMode.MAIN)

WordPress/src/main/java/org/wordpress/android/ui/posts/GutenbergKitSettingsBuilder.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@ object GutenbergKitSettingsBuilder {
5454
val remotePostId: Long?,
5555
val isPage: Boolean,
5656
val title: String?,
57-
val content: String?
57+
val content: String?,
58+
val status: String?
5859
) {
5960
companion object {
6061
fun fromPostModel(postModel: PostImmutableModel?): PostConfig {
6162
return PostConfig(
6263
remotePostId = postModel?.remotePostId,
6364
isPage = postModel?.isPage ?: false,
6465
title = postModel?.title,
65-
content = postModel?.content
66+
content = postModel?.content,
67+
status = postModel?.status
6668
)
6769
}
6870
}
@@ -127,6 +129,7 @@ object GutenbergKitSettingsBuilder {
127129
return mutableMapOf(
128130
"postId" to postConfig.remotePostId?.toInt(),
129131
"postType" to if (postConfig.isPage) "page" else "post",
132+
"status" to postConfig.status,
130133
"postTitle" to postConfig.title,
131134
"postContent" to postConfig.content,
132135
"siteURL" to siteConfig.url,

WordPress/src/main/java/org/wordpress/android/ui/posts/editor/GutenbergKitEditorFragment.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,19 @@ class GutenbergKitEditorFragment : GutenbergKitEditorFragmentBase() {
201201
gutenbergView::setNetworkRequestListener
202202
)
203203

204+
// Set up content provider for WebView refresh recovery
205+
gutenbergView.setLatestContentProvider(
206+
object : GutenbergView.LatestContentProvider {
207+
override fun getLatestContent(): GutenbergView.LatestContent {
208+
return GutenbergView.LatestContent(
209+
mEditorFragmentListener.persistedTitle,
210+
mEditorFragmentListener.persistedContent
211+
)
212+
}
213+
}
214+
)
215+
216+
// Set up autocomplete listener for user mentions and cross-post suggestions
204217
gutenbergView.setAutocompleterTriggeredListener(
205218
object : GutenbergView.AutocompleterTriggeredListener {
206219
override fun onAutocompleterTriggered(type: String) {

WordPress/src/main/java/org/wordpress/android/ui/posts/editor/GutenbergKitEditorFragmentBase.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,17 @@ public interface EditorFragmentListener extends DialogVisibilityProvider {
151151
void onOpenMediaLibraryRequested(org.wordpress.gutenberg.GutenbergView.OpenMediaLibraryConfig config);
152152
void onModalDialogOpened(String dialogType);
153153
void onModalDialogClosed(String dialogType);
154+
155+
/**
156+
* Returns the persisted post title for content recovery after WebView refresh.
157+
* @return The most recently persisted title from autosave.
158+
*/
159+
String getPersistedTitle();
160+
161+
/**
162+
* Returns the persisted post content for content recovery after WebView refresh.
163+
* @return The most recently persisted content from autosave.
164+
*/
165+
String getPersistedContent();
154166
}
155167
}

WordPress/src/test/java/org/wordpress/android/ui/posts/GutenbergKitSettingsBuilderTest.kt

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ class GutenbergKitSettingsBuilderTest {
409409
remotePostId = 456L,
410410
isPage = false,
411411
title = "Test Post",
412-
content = "Test Content"
412+
content = "Test Content",
413+
status = "publish"
413414
)
414415

415416
val settings = GutenbergKitSettingsBuilder.buildSettings(
@@ -461,7 +462,8 @@ class GutenbergKitSettingsBuilderTest {
461462
remotePostId = 100L,
462463
isPage = true,
463464
title = "Test Page",
464-
content = "Page Content"
465+
content = "Page Content",
466+
status = "draft"
465467
)
466468

467469
val settings = GutenbergKitSettingsBuilder.buildSettings(
@@ -579,7 +581,8 @@ class GutenbergKitSettingsBuilderTest {
579581
remotePostId = null,
580582
isPage = false,
581583
title = null,
582-
content = null
584+
content = null,
585+
status = null
583586
)
584587

585588
val settings = GutenbergKitSettingsBuilder.buildSettings(
@@ -594,9 +597,30 @@ class GutenbergKitSettingsBuilderTest {
594597
assertThat(settings["postId"]).isNull()
595598
assertThat(settings["postTitle"]).isNull()
596599
assertThat(settings["postContent"]).isNull()
600+
assertThat(settings["status"]).isNull()
597601
assertThat(settings["postType"]).isEqualTo("post") // Still defaults to post
598602
}
599603

604+
@Test
605+
fun `post status is included in settings`() {
606+
val testCases = listOf("draft", "publish", "pending", "private", "future", "trash")
607+
608+
testCases.forEach { status ->
609+
val postConfig = createPostConfig(status = status)
610+
611+
val settings = GutenbergKitSettingsBuilder.buildSettings(
612+
siteConfig = createSiteConfig(),
613+
postConfig = postConfig,
614+
appConfig = createAppConfig(),
615+
featureConfig = createFeatureConfig()
616+
)
617+
618+
assertThat(settings["status"])
619+
.withFailMessage("Expected status=$status in settings")
620+
.isEqualTo(status)
621+
}
622+
}
623+
600624
// ===== Helper Methods =====
601625

602626
private fun createFeatureConfig(
@@ -651,11 +675,13 @@ class GutenbergKitSettingsBuilderTest {
651675
remotePostId: Long? = 1L,
652676
isPage: Boolean = false,
653677
title: String? = "Test",
654-
content: String? = "Content"
678+
content: String? = "Content",
679+
status: String? = "draft"
655680
) = GutenbergKitSettingsBuilder.PostConfig(
656681
remotePostId = remotePostId,
657682
isPage = isPage,
658683
title = title,
659-
content = content
684+
content = content,
685+
status = status
660686
)
661687
}

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ google-play-review = '2.0.2'
7373
google-services = '4.4.4'
7474
gravatar = '2.5.0'
7575
greenrobot-eventbus = '3.3.1'
76-
gutenberg-kit = 'v0.15.0'
76+
gutenberg-kit = '432-944fbfce704642cfe725dc69c03b3cf6d5018854'
7777
gutenberg-mobile = 'v1.121.0'
7878
indexos-media-for-mobile = '43a9026f0973a2f0a74fa813132f6a16f7499c3a'
7979
jackson-databind = '2.12.7.1'

0 commit comments

Comments
 (0)