Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<EnvironmentVariable
key = "GUTENBERG_EDITOR_URL"
value = "http://localhost:5173/"
isEnabled = "NO">
isEnabled = "YES">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since #191 (comment), should we enable GUTENBERG_EDITOR_URL by default? I keep doing this every time I work on the editor.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good to me. However, let's also enable the GUTENBERG_EDITOR_REMOTE_URL environment variable as well.

We should also update the README documentation to match the new default settings. The README recently changed. I suggest rebasing this atop the latest trunk branch and applying the following diff

diff --git a/README.md b/README.md
index 977bcba..9993c75 100644
--- a/README.md
+++ b/README.md
@@ -26,17 +26,19 @@ Once finished, the web app can now be accessed in your browser by visiting the U
 
 ### Demo App
 
-This demo app is useful for quickly testing changes made to the editor. By default, the demo app uses a production build of the web app bundled with the GutenbergKit package—i.e., the output of the project's `make build` command. During development, however, it is more useful to run the web app with a server and provide the server URL as an environment variable for the demo app, so that changes are displayed in the app immediately.
+This demo app is useful for quickly testing changes made to the editor.
 
 #### iOS
 
+The iOS demo app loads the development server by default.
+
 1. Start the development server by running `make dev-server`.
 1. Launch Xcode and open the `ios/Demo-iOS/Gutenberg.xcodeproj` project.
 1. Select the `Gutenberg` target.
-1. Navigate to _Product_ → _Scheme_ → _Edit Scheme_.
-1. Add an environment variable named `GUTENBERG_EDITOR_URL` with the development server URL.
 1. Run the app.
 
+Alternatively, you can load a production build of the web app bundled with the GutenbergKit package by running `make build` and disabling the `GUTENBERG_EDITOR_URL` environment variable by navigating to _Product_ → _Scheme_ → _Edit Scheme_ in Xcode.
+
 <details>
 <summary>Example Xcode environment variable</summary>
 
@@ -46,6 +48,8 @@ This demo app is useful for quickly testing changes made to the editor. By defau
 
 #### Android
 
+The Android demo app loads the production build of the web app bundled with the GutenbergKit package by default—i.e., the output of the project's `make build` command). It can be configured to load the development server by setting a `GUTENBERG_EDITOR_URL` environment variable in the `android/local.properties` file.
+
 1. Start the development server by running `make dev-server`.
 1. Launch Android Studio and open the `android` project.
 1. Modify the `android/local.properties` file to include an environment variable named `GUTENBERG_EDITOR_URL` with the development server URL.

</EnvironmentVariable>
<EnvironmentVariable
key = "GUTENBERG_EDITOR_REMOTE_URL"
Expand Down
67 changes: 49 additions & 18 deletions ios/Demo-iOS/Sources/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import SwiftUI
import GutenbergKit

let editorURL: URL? = ProcessInfo.processInfo.environment["GUTENBERG_EDITOR_URL"].flatMap(URL.init)

struct ContentView: View {
private let remoteEditors: [RemoteEditorRow] = [
.init(id: "template", configuration: .template)
]

@State private var isDefaultEditorShown = false
@State private var selectedRemoteEditor: RemoteEditorRow?

let remoteEditorConfigurations: [EditorConfiguration] = [.template]
@AppStorage("isNativeInserterEnabled") private var isNativeInserterEnabled = false

var body: some View {
List {
Section {
NavigationLink {
EditorView(configuration: .default)
} label: {
Text("Bundled Editor")
Button("Show Editor") {
Copy link
Member

Choose a reason for hiding this comment

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

I suggest retaining "bundled" somewhere to differentiate from the remote editors and remain aligned with Android's demo app/project documentation.

isDefaultEditorShown = true
}
}

Section {
ForEach(remoteEditorConfigurations, id: \.siteURL) { configuration in
NavigationLink {
EditorView(configuration: configuration)
} label: {
Text(URL(string: configuration.siteURL)?.host ?? configuration.siteURL)
ForEach(remoteEditors) { editor in
Button(editor.title) {
selectedRemoteEditor = editor
}
}

if remoteEditorConfigurations.isEmpty {
if remoteEditors.isEmpty {
Text("Add `EditorConfiguration` instances to the `remoteEditorConfigurations` array to launch remote editors here.")
}
} header: {
Expand All @@ -38,18 +38,32 @@ struct ContentView: View {
Text("Note: The editor is backed by the compiled web app created by `make build`.")
}
}

Section("Configuration") {
Toggle("Native Inserter", isOn: $isNativeInserterEnabled)
}
}
.fullScreenCover(isPresented: $isDefaultEditorShown) {
NavigationView {
EditorView(configuration: preconfigure(.default))
}
}
.fullScreenCover(item: $selectedRemoteEditor) { editor in
NavigationView {
EditorView(configuration: preconfigure(editor.configuration))
}
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
Task {
NSLog("Start to fetch assets")
for configuration in remoteEditorConfigurations {
let library = EditorAssetsLibrary(configuration: configuration)
for editor in remoteEditors {
let library = EditorAssetsLibrary(configuration: editor.configuration)
do {
try await library.fetchAssets()
} catch {
NSLog("Failed to fetch assets for \(configuration.siteURL): \(error)")
NSLog("Failed to fetch assets for \(editor.configuration.siteURL): \(error)")
}
}
NSLog("Done fetching assets")
Expand All @@ -61,13 +75,30 @@ struct ContentView: View {
}
}
}

private func preconfigure(_ configuration: EditorConfiguration) -> EditorConfiguration {
configuration
.toBuilder()
.setNativeInserterEnabled(isNativeInserterEnabled)
.build()
}
}

private struct RemoteEditorRow: Identifiable {
let id: String
let configuration: EditorConfiguration

var title: String {
URL(string: configuration.siteURL)?.host ?? configuration.siteURL
}
}

private extension EditorConfiguration {

static var template: Self {
#warning("1. Update the siteURL and authHeader values below")
#warning("2. Install the Jetpack plugin to the site")
// Steps:
// 1. Update the siteURL and authHeader values below
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These shouldn't be warnings.

// 2. Install the Jetpack plugin to the site
let siteUrl: String = "https://modify-me.com"
let authHeader: String = "Insert the Authorization header value here"
let siteApiRoot: String = "\(siteUrl)/wp-json/"
Expand Down
2 changes: 0 additions & 2 deletions ios/Demo-iOS/Sources/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ struct EditorView: View {
private let configuration: EditorConfiguration

@State private var viewModel = EditorViewModel()
@State private var editorViewController: EditorViewController?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Follow-up to the previous PR


@Environment(\.dismiss) private var dismiss

Expand All @@ -15,7 +14,6 @@ struct EditorView: View {

var body: some View {
_EditorView(configuration: configuration, viewModel: viewModel)
.navigationBarBackButtonHidden(true)
.toolbar { toolbar }
}

Expand Down
16 changes: 16 additions & 0 deletions ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public struct EditorConfiguration: Sendable {
public let editorSettings: String
/// Locale used for translations
public let locale: String
/// Enables the native inserter UI in the editor
public let isNativeInserterEnabled: Bool
/// Endpoint for loading editor assets, used when enabling `shouldUsePlugins`
public var editorAssetsEndpoint: URL?

Expand All @@ -49,6 +51,7 @@ public struct EditorConfiguration: Sendable {
authHeader: String,
editorSettings: String,
locale: String,
isNativeInserterEnabled: Bool,
editorAssetsEndpoint: URL? = nil,
) {
self.title = title
Expand All @@ -65,6 +68,7 @@ public struct EditorConfiguration: Sendable {
self.authHeader = authHeader
self.editorSettings = editorSettings
self.locale = locale
self.isNativeInserterEnabled = isNativeInserterEnabled
self.editorAssetsEndpoint = editorAssetsEndpoint
}

Expand All @@ -84,6 +88,7 @@ public struct EditorConfiguration: Sendable {
authHeader: authHeader,
editorSettings: editorSettings,
locale: locale,
isNativeInserterEnabled: isNativeInserterEnabled,
editorAssetsEndpoint: editorAssetsEndpoint
)
}
Expand Down Expand Up @@ -114,6 +119,7 @@ public struct EditorConfigurationBuilder {
private var authHeader: String
private var editorSettings: String
private var locale: String
private var isNativeInserterEnabled: Bool
private var editorAssetsEndpoint: URL?

public init(
Expand All @@ -131,6 +137,7 @@ public struct EditorConfigurationBuilder {
authHeader: String = "",
editorSettings: String = "undefined",
locale: String = "en",
isNativeInserterEnabled: Bool = false,
editorAssetsEndpoint: URL? = nil
){
self.title = title
Expand All @@ -147,6 +154,7 @@ public struct EditorConfigurationBuilder {
self.authHeader = authHeader
self.editorSettings = editorSettings
self.locale = locale
self.isNativeInserterEnabled = isNativeInserterEnabled
self.editorAssetsEndpoint = editorAssetsEndpoint
}

Expand Down Expand Up @@ -234,6 +242,12 @@ public struct EditorConfigurationBuilder {
return copy
}

public func setNativeInserterEnabled(_ isNativeInserterEnabled: Bool = true) -> EditorConfigurationBuilder {
var copy = self
copy.isNativeInserterEnabled = isNativeInserterEnabled
return copy
}

public func setEditorAssetsEndpoint(_ editorAssetsEndpoint: URL?) -> EditorConfigurationBuilder {
var copy = self
copy.editorAssetsEndpoint = editorAssetsEndpoint
Expand Down Expand Up @@ -278,6 +292,7 @@ public struct EditorConfigurationBuilder {
authHeader: authHeader,
editorSettings: editorSettings,
locale: locale,
isNativeInserterEnabled: isNativeInserterEnabled,
editorAssetsEndpoint: editorAssetsEndpoint
)
}
Expand All @@ -296,3 +311,4 @@ private extension String {
.replacingOccurrences(of: "\u{12}", with: "\\f")
}
}

6 changes: 5 additions & 1 deletion ios/Sources/GutenbergKit/Sources/EditorJSMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct EditorJSMessage {
/// The editor logged an exception.
case onEditorExceptionLogged
/// The user tapped the inserter button.
case showBlockPicker
case showBlockInserter
/// User requested the Media Library.
case openMediaLibrary
/// The user triggered an autocompleter.
Expand Down Expand Up @@ -65,4 +65,8 @@ struct EditorJSMessage {
struct ModalDialogBody: Decodable {
let dialogType: String
}

struct ShowBlockInserterBody: Decodable {
let blocks: [EditorBlock]
}
}
20 changes: 10 additions & 10 deletions ios/Sources/GutenbergKit/Sources/EditorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro
namespaceExcludedPaths: \(Array(configuration.namespaceExcludedPaths)),
authHeader: '\(configuration.authHeader)',
themeStyles: \(configuration.shouldUseThemeStyles),
enableNativeBlockInserter: \(configuration.isNativeInserterEnabled),
hideTitle: \(configuration.shouldHideTitle),
editorSettings: \(configuration.editorSettings),
locale: '\(configuration.locale)',
Expand Down Expand Up @@ -265,14 +266,12 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro

// MARK: - Internal (Block Inserter)

// TODO: wire with JS and pass blocks
private func showBlockInserter() {
// let viewModel = EditorBlockPickerViewModel(blockTypes: service.blockTypes)
// let view = NavigationView {
// EditorBlockPicker(viewModel: viewModel)
// }
// let host = UIHostingController(rootView: view)
// present(host, animated: true)
private func showBlockInserter(blocks: [EditorBlock]) {
present(UIHostingController(rootView: NavigationView {
List(blocks) {
Text($0.name)
}
}), animated: true)
}

private func openMediaLibrary(_ config: OpenMediaLibraryAction) {
Expand Down Expand Up @@ -315,8 +314,9 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro
return
}
delegate?.editor(self, didLogException: editorException)
case .showBlockPicker:
showBlockInserter()
case .showBlockInserter:
let body = try message.decode(EditorJSMessage.ShowBlockInserterBody.self)
showBlockInserter(blocks: body.blocks)
case .openMediaLibrary:
let config = try message.decode(OpenMediaLibraryAction.self)
openMediaLibrary(config)
Expand Down
38 changes: 29 additions & 9 deletions src/components/editor-toolbar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
ToolbarButton,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { close, cog } from '@wordpress/icons';
import { close, cog, plus } from '@wordpress/icons';
import clsx from 'clsx';
import { store as editorStore } from '@wordpress/editor';

Expand All @@ -27,6 +27,8 @@ import { store as editorStore } from '@wordpress/editor';
import './style.scss';
import { useModalize } from './use-modalize';
import { useModalDialogState } from '../editor/use-modal-dialog-state';
import { showBlockInserter, getGBKit } from '../../utils/bridge';


/**
* Renders the editor toolbar containing block-related actions.
Expand All @@ -36,6 +38,8 @@ import { useModalDialogState } from '../editor/use-modal-dialog-state';
* @return {JSX.Element} The rendered editor toolbar component.
*/
const EditorToolbar = ( { className } ) => {
const { enableNativeBlockInserter } = getGBKit();

const [ isBlockInspectorShown, setBlockInspectorShown ] = useState( false );
const { isSelected } = useSelect( ( select ) => {
const { getSelectedBlockClientId } = select( blockEditorStore );
Expand Down Expand Up @@ -77,6 +81,29 @@ const EditorToolbar = ( { className } ) => {

const classes = clsx( 'gutenberg-kit-editor-toolbar', className );

const addBlockButton = enableNativeBlockInserter ? (
<ToolbarButton
title={ __( 'Add block' ) }
icon={ plus }
onClick={ () => {
if ( isInserterOpened ) {
setIsInserterOpened( false );
}
Comment on lines +88 to +90
Copy link
Member

Choose a reason for hiding this comment

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

Is this achieving a specific outcome?

showBlockInserter();
} }
className="gutenberg-kit-add-block-button"
/>
) : (
<Inserter
popoverProps={ {
'aria-modal': true,
role: 'dialog',
} }
open={ isInserterOpened }
onToggle={ setIsInserterOpened }
/>
);

return (
<>
<Toolbar
Expand All @@ -85,14 +112,7 @@ const EditorToolbar = ( { className } ) => {
variant="unstyled"
>
<ToolbarGroup>
<Inserter
popoverProps={ {
'aria-modal': true,
role: 'dialog',
} }
open={ isInserterOpened }
onToggle={ setIsInserterOpened }
/>
{ addBlockButton }
</ToolbarGroup>

{ isSelected && (
Expand Down
16 changes: 16 additions & 0 deletions src/components/editor-toolbar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,19 @@ $min-touch-target-size: 46px;
left: 6px;
right: 6px;
}

// Style the add block button with rounded black background
.gutenberg-kit-editor-toolbar .gutenberg-kit-add-block-button {
Copy link
Contributor Author

@kean kean Oct 9, 2025

Choose a reason for hiding this comment

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

I don't feel strongly about it, but ToolbarButton needed some design. I don't think it needs to stand out as much as it currently does (a single black spot on the entire screen).

Screenshot 2025-10-09 at 10 59 19 AM

Copy link
Member

Choose a reason for hiding this comment

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

I think this is fine for now. Eventually, we need to consideration Android design patterns.

svg {
background: #eae9ec;
border-radius: 18px;
color: wordpress.$black;
padding: 1px;
width: 32px;
height: 32px;
display: block;
}
Comment on lines +77 to +85
Copy link
Member

Choose a reason for hiding this comment

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

I suggest we place this after the attributes declared for .gutenberg-kit-editor-toolbar .gutenberg-kit-add-block-button. I.e., move this after the current line 88.


// width: 50px;
Copy link
Member

Choose a reason for hiding this comment

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

This commented code should likely be removed.

margin-left: 8px;
}
Loading
Loading