Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
550a588
refactor: Provide editor settings to GutenbergKit
dcalhoun Apr 7, 2025
2727408
refactor: Move onEditorSettingsChanged subscription to EditPostActivity
dcalhoun Apr 7, 2025
14f99cc
style: Automated formatting changes
dcalhoun Apr 8, 2025
0de6ee0
feat: Dispatch editor settings request
dcalhoun Apr 8, 2025
00438a3
refactor: Improve editor settings parsing
dcalhoun Apr 8, 2025
a9710cb
refactor: Simplify EditorSettings
dcalhoun Apr 8, 2025
7ae1aa5
refactor: Pass editor settings as JSON string
dcalhoun Apr 8, 2025
37df679
feat: Display activity indicator while fetching editor settings
dcalhoun Apr 9, 2025
dd7a59d
feat: Add cache-while-revalidate for editor settings
dcalhoun Apr 9, 2025
2e0a1dc
feat: Persist editor settings in SQLite
dcalhoun Apr 9, 2025
6ea9561
build: Update GutenbergKit ref
dcalhoun Apr 9, 2025
1434de3
style: Address lint errors
dcalhoun Apr 9, 2025
acad23b
style: Address lint warnings
dcalhoun Apr 9, 2025
d38bf79
fix: Use -1 post ID for new drafts
dcalhoun Apr 11, 2025
c6f73b0
Revert "style: Automated formatting changes"
dcalhoun Apr 11, 2025
119bf6c
refactor: Remove unnecessary style configuration
dcalhoun Apr 11, 2025
074a3f6
refactor: Avoid redundant editor starts
dcalhoun Apr 11, 2025
c9c358a
build: Update GutenbergKit ref
dcalhoun Apr 11, 2025
948efd9
style: Address lint warning
dcalhoun Apr 11, 2025
dd7f3a8
fix: Start editor with default settings on failed editor settings
dcalhoun Apr 12, 2025
9067f91
fix: Emit available cached editor settings on fetch failure
dcalhoun Apr 12, 2025
d99dc81
build: Update GutenbergKit ref
dcalhoun Apr 24, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import com.automattic.android.tracks.crashlogging.JsExceptionStackTraceElement
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.gson.JsonObject
import kotlinx.parcelize.parcelableCreator
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
Expand Down Expand Up @@ -82,11 +83,13 @@ import org.wordpress.android.editor.savedinstance.SavedInstanceDatabase.Companio
import org.wordpress.android.fluxc.Dispatcher
import org.wordpress.android.fluxc.action.AccountAction
import org.wordpress.android.fluxc.generated.AccountActionBuilder
import org.wordpress.android.fluxc.generated.EditorSettingsActionBuilder
import org.wordpress.android.fluxc.generated.EditorThemeActionBuilder
import org.wordpress.android.fluxc.generated.PostActionBuilder
import org.wordpress.android.fluxc.generated.SiteActionBuilder
import org.wordpress.android.fluxc.model.AccountModel
import org.wordpress.android.fluxc.model.CauseOfOnPostChanged
import org.wordpress.android.fluxc.model.EditorSettings
import org.wordpress.android.fluxc.model.EditorTheme
import org.wordpress.android.fluxc.model.EditorThemeSupport
import org.wordpress.android.fluxc.model.MediaModel
Expand All @@ -99,6 +102,9 @@ import org.wordpress.android.fluxc.network.UserAgent
import org.wordpress.android.fluxc.network.rest.wpcom.site.PrivateAtomicCookie
import org.wordpress.android.fluxc.store.AccountStore
import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged
import org.wordpress.android.fluxc.store.EditorSettingsStore
import org.wordpress.android.fluxc.store.EditorSettingsStore.FetchEditorSettingsPayload
import org.wordpress.android.fluxc.store.EditorSettingsStore.OnEditorSettingsChanged
import org.wordpress.android.fluxc.store.EditorThemeStore
import org.wordpress.android.fluxc.store.EditorThemeStore.FetchEditorThemePayload
import org.wordpress.android.fluxc.store.EditorThemeStore.OnEditorThemeChanged
Expand Down Expand Up @@ -348,6 +354,8 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor

@Inject lateinit var editorThemeStore: EditorThemeStore

@Inject lateinit var editorSettingsStore: EditorSettingsStore

@Inject lateinit var imageLoader: FluxCImageLoader

@Inject lateinit var shortcutUtils: ShortcutUtils
Expand Down Expand Up @@ -3636,9 +3644,12 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
}

private fun onEditorFinalTouchesBeforeShowing() {
refreshEditorContent()
if (editorFragment !is GutenbergKitEditorFragment) {
refreshEditorContent()
}
Comment on lines +3647 to +3649
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timing of this content refresh is currently incompatible with/unnecessary for GutenbergKit.


onEditorFinalTouchesBeforeShowingForGutenbergIfNeeded()
onEditorFinalTouchesBeforeShowingForGutenbergKitIfNeeded()
onEditorFinalTouchesBeforeShowingForAztecIfNeeded()
}
private fun onEditorFinalTouchesBeforeShowingForGutenbergIfNeeded() {
Expand All @@ -3661,6 +3672,13 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
(editorFragment as GutenbergEditorFragment).resetUploadingMediaToFailed(mediaIds)
}
}

private fun onEditorFinalTouchesBeforeShowingForGutenbergKitIfNeeded() {
if (showGutenbergEditor && editorFragment is GutenbergKitEditorFragment) {
refreshEditorSettings()
}
}

private fun onEditorFinalTouchesBeforeShowingForAztecIfNeeded() {
if (showAztecEditor && editorFragment is AztecEditorFragment) {
val entryPoint =
Expand Down Expand Up @@ -4065,6 +4083,18 @@ class EditPostActivity : BaseAppCompatActivity(), EditorFragmentActivity, Editor
postEditorAnalyticsSession?.editorSettingsFetched(editorThemeSupport.isBlockBasedTheme, event.endpoint.value)
}

private fun refreshEditorSettings() {
val payload = FetchEditorSettingsPayload(siteModel)
dispatcher.dispatch(EditorSettingsActionBuilder.newFetchEditorSettingsAction(payload))
}

@Suppress("unused")
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
fun onEditorSettingsChanged(event: OnEditorSettingsChanged) {
val editorSettings = event.editorSettings ?: EditorSettings(JsonObject())
(editorFragment as? GutenbergKitEditorFragment)?.startWithEditorSettings(editorSettings.toJsonString())
}

// EditPostActivityHook methods
override fun getEditPostRepository() = editPostRepository
override fun getSite() = siteModel
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ google-play-services-auth = '20.4.1'
google-services = '4.4.2'
gravatar = '2.4.1'
greenrobot-eventbus = '3.3.1'
gutenberg-kit = 'trunk-a03e0dae10a404c88c215bfcee3176df951302f5'
gutenberg-kit = 'trunk-fa72e630203e7472d55f4abedfd5c462d2333584'
gutenberg-mobile = 'v1.121.0'
indexos-media-for-mobile = '43a9026f0973a2f0a74fa813132f6a16f7499c3a'
jackson-databind = '2.12.7.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,16 @@ public class GutenbergKitEditorFragment extends EditorFragmentAbstract implement
@Nullable private LogJsExceptionListener mOnLogJsExceptionListener = null;

private boolean mEditorDidMount;
@Nullable
private View mRootView;

@Nullable private static Map<String, Object> mSettings;

public static GutenbergKitEditorFragment newInstance(Context context,
boolean isNewPost,
GutenbergWebViewAuthorizationData webViewAuthorizationData,
boolean jetpackFeaturesEnabled,
@Nullable Map<String, Object> settings) {
boolean isNewPost,
@Nullable GutenbergWebViewAuthorizationData webViewAuthorizationData,
boolean jetpackFeaturesEnabled,
@Nullable Map<String, Object> settings) {
GutenbergKitEditorFragment fragment = new GutenbergKitEditorFragment();
Bundle args = new Bundle();
args.putBoolean(ARG_IS_NEW_POST, isNewPost);
Expand Down Expand Up @@ -137,11 +139,20 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
((EditorFragmentActivity) getActivity()).initializeEditorFragment();
}

mEditorFragmentListener.onEditorFragmentInitialized();

mRootView = inflater.inflate(R.layout.fragment_gutenberg_kit_editor, container, false);
ViewGroup gutenbergViewContainer = mRootView.findViewById(R.id.gutenberg_view_container);

mGutenbergView = GutenbergWebViewPool.getPreloadedWebView(requireContext());
mGutenbergView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
));
gutenbergViewContainer.addView(mGutenbergView);

setEditorProgressBarVisibility(true);

mGutenbergView.setOnFileChooserRequestedListener((intent, requestCode) -> {
startActivityForResult(intent, requestCode);
return null;
Expand All @@ -151,31 +162,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
mGutenbergView.setOpenMediaLibraryListener(mOpenMediaLibraryListener);
mGutenbergView.setLogJsExceptionListener(mOnLogJsExceptionListener);
mGutenbergView.setEditorDidBecomeAvailable(view -> {
mEditorDidMount = true;
mEditorFragmentListener.onEditorFragmentContentReady(new ArrayList<>(), false);
setEditorProgressBarVisibility(false);
});

Integer postId = (Integer) mSettings.get("postId");
if (postId != null && postId == 0) {
postId = -1;
}

EditorConfiguration config = new EditorConfiguration.Builder()
.setTitle((String) mSettings.get("postTitle"))
.setContent((String) mSettings.get("postContent"))
.setPostId(postId)
.setPostType((String) mSettings.get("postType"))
.setThemeStyles((Boolean) mSettings.get("themeStyles"))
.setPlugins((Boolean) mSettings.get("plugins"))
.setSiteApiRoot((String) mSettings.get("siteApiRoot"))
.setSiteApiNamespace((String[]) mSettings.get("siteApiNamespace"))
.setNamespaceExcludedPaths((String[]) mSettings.get("namespaceExcludedPaths"))
.setAuthHeader((String) mSettings.get("authHeader"))
.setWebViewGlobals((List<WebViewGlobal>) mSettings.get("webViewGlobals"))
.build();

mGutenbergView.start(config);

return mGutenbergView;
return mRootView;
}

@Override public void onConfigurationChanged(@NonNull Configuration newConfig) {
Expand Down Expand Up @@ -218,6 +210,13 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d

@Override public void onResume() {
super.onResume();
setEditorProgressBarVisibility(!mEditorDidMount);
}

private void setEditorProgressBarVisibility(boolean shown) {
if (isAdded() && mRootView != null) {
mRootView.findViewById(R.id.editor_progress).setVisibility(shown ? View.VISIBLE : View.GONE);
}
}

@Override
Expand Down Expand Up @@ -543,6 +542,34 @@ public void onEditorThemeUpdated(Bundle editorTheme) {
// Unused, no-op retained for the shared interface with Gutenberg
}

public void startWithEditorSettings(@NonNull String editorSettings) {
if (mGutenbergView == null) {
return;
}

Integer postId = (Integer) mSettings.get("postId");
if (postId != null && postId == 0) {
postId = -1;
}

EditorConfiguration config = new EditorConfiguration.Builder()
.setTitle((String) mSettings.get("postTitle"))
.setContent((String) mSettings.get("postContent"))
.setPostId(postId)
.setPostType((String) mSettings.get("postType"))
.setThemeStyles((Boolean) mSettings.get("themeStyles"))
.setPlugins((Boolean) mSettings.get("plugins"))
.setSiteApiRoot((String) mSettings.get("siteApiRoot"))
.setSiteApiNamespace((String[]) mSettings.get("siteApiNamespace"))
.setNamespaceExcludedPaths((String[]) mSettings.get("namespaceExcludedPaths"))
.setAuthHeader((String) mSettings.get("authHeader"))
.setWebViewGlobals((List<WebViewGlobal>) mSettings.get("webViewGlobals"))
.setEditorSettings(editorSettings)
.build();

mGutenbergView.start(config);
}

@Override
public void showNotice(String message) {
// Unused, no-op retained for the shared interface with Gutenberg
Expand Down
18 changes: 18 additions & 0 deletions libs/editor/src/main/res/layout/fragment_gutenberg_kit_editor.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gutenberg_kit_container"
android:layout_height="match_parent"
android:layout_width="match_parent">

<FrameLayout
android:id="@+id/gutenberg_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<ProgressBar
android:id="@+id/editor_progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.wordpress.android.fluxc.action

import org.wordpress.android.fluxc.annotations.Action
import org.wordpress.android.fluxc.annotations.ActionEnum
import org.wordpress.android.fluxc.annotations.action.IAction
import org.wordpress.android.fluxc.store.EditorSettingsStore.FetchEditorSettingsPayload

@ActionEnum
enum class EditorSettingsAction : IAction {
@Action(payloadType = FetchEditorSettingsPayload::class)
FETCH_EDITOR_SETTINGS
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.wordpress.android.fluxc.action

import org.wordpress.android.fluxc.annotations.action.Action
import org.wordpress.android.fluxc.store.EditorSettingsStore.FetchEditorSettingsPayload

object EditorSettingsActionBuilder {
fun newFetchEditorSettingsAction(payload: FetchEditorSettingsPayload): Action<FetchEditorSettingsPayload> {
return Action(EditorSettingsAction.FETCH_EDITOR_SETTINGS, payload)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.wordpress.android.fluxc.model

import com.google.gson.JsonObject
import org.wordpress.android.fluxc.persistence.EditorSettingsSqlUtils.EditorSettingsBuilder

class EditorSettings(val rawSettings: JsonObject) {
fun toJsonString(): String {
return rawSettings.toString()
}

fun toBuilder(site: SiteModel): EditorSettingsBuilder {
return EditorSettingsBuilder().apply {
localSiteId = site.id
rawSettings = this@EditorSettings.rawSettings.toString()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.wordpress.android.fluxc.persistence

import com.google.gson.JsonParser
import com.wellsql.generated.EditorSettingsTable
import com.yarolegovich.wellsql.WellSql
import com.yarolegovich.wellsql.core.Identifiable
import com.yarolegovich.wellsql.core.annotation.Column
import com.yarolegovich.wellsql.core.annotation.PrimaryKey
import com.yarolegovich.wellsql.core.annotation.Table
import org.wordpress.android.fluxc.model.EditorSettings
import org.wordpress.android.fluxc.model.SiteModel

class EditorSettingsSqlUtils {
fun replaceEditorSettingsForSite(site: SiteModel, editorSettings: EditorSettings?) {
deleteEditorSettingsForSite(site)
if (editorSettings == null) return
makeEditorSettings(site, editorSettings)
}

fun getEditorSettingsForSite(site: SiteModel): EditorSettings? {
return WellSql.select(EditorSettingsBuilder::class.java)
.limit(1)
.where()
.equals(EditorSettingsTable.LOCAL_SITE_ID, site.id)
.endWhere()
.asModel
.firstOrNull()
?.toEditorSettings()
}

fun deleteEditorSettingsForSite(site: SiteModel) {
WellSql.delete(EditorSettingsBuilder::class.java)
.where()
.equals(EditorSettingsTable.LOCAL_SITE_ID, site.id)
.endWhere()
.execute()
}

private fun makeEditorSettings(site: SiteModel, editorSettings: EditorSettings) {
val builder = editorSettings.toBuilder(site)
WellSql.insert(builder).execute()
}

@Table(name = "EditorSettings")
data class EditorSettingsBuilder(@PrimaryKey @Column private var mId: Int = -1) : Identifiable {
@Column var localSiteId: Int = -1
@JvmName("getLocalSiteId")
get
@JvmName("setLocalSiteId")
set
@Column var rawSettings: String? = null

override fun setId(id: Int) {
this.mId = id
}

override fun getId() = mId

fun toEditorSettings(): EditorSettings? {
return rawSettings?.let {
val jsonObject = JsonParser.parseString(it).asJsonObject
EditorSettings(jsonObject)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ open class WellSqlConfig : DefaultWellConfig {
annotation class AddOn

override fun getDbVersion(): Int {
return 205
return 206
}

override fun getDbName(): String {
Expand Down Expand Up @@ -2055,6 +2055,17 @@ open class WellSqlConfig : DefaultWellConfig {
}

204 -> db.execSQL("ALTER TABLE SiteModel ADD IS_DELETED INTEGER DEFAULT 0")

205 -> migrate(version) {
db.execSQL("""
CREATE TABLE IF NOT EXISTS EditorSettings (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
LOCAL_SITE_ID INTEGER NOT NULL,
RAW_SETTINGS TEXT,
FOREIGN KEY (LOCAL_SITE_ID) REFERENCES SiteModel(_id) ON DELETE CASCADE
)
""".trimIndent())
}
}
}
db.setTransactionSuccessful()
Expand Down
Loading