Skip to content

Commit 932ffc4

Browse files
committed
Implemnet block insertion
1 parent 29a7bd1 commit 932ffc4

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

ios/Sources/GutenbergKit/Sources/EditorViewController.swift

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,17 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro
240240
// MARK: - Internal (Block Inserter)
241241

242242
private func showBlockInserter(blocks: [EditorBlock]) {
243-
present(UIHostingController(rootView: NavigationView {
244-
BlockInserterView(blocks: blocks) {
245-
print("did select:", $0)
243+
// Capture the selected block ID before showing the inserter
244+
// (the editor will lose focus when the modal appears)
245+
Task { @MainActor in
246+
let selectedBlockID = await getSelectedBlockID()
247+
let inserterView = NavigationView {
248+
BlockInserterView(blocks: blocks) { [weak self] block in
249+
self?.insertBlock(block.name, selectedBlockID: selectedBlockID)
250+
}
246251
}
247-
}), animated: true)
252+
present(UIHostingController(rootView: inserterView), animated: true)
253+
}
248254
}
249255

250256
private func openMediaLibrary(_ config: OpenMediaLibraryAction) {
@@ -263,6 +269,25 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro
263269
evaluate("editor.appendTextAtCursor(decodeURIComponent('\(escapedText)'));")
264270
}
265271

272+
/// Gets the currently selected block client ID.
273+
///
274+
/// - returns: The selected block client ID, or nil if no block is selected.
275+
private func getSelectedBlockID() async -> String? {
276+
try? await webView.evaluateJavaScript("editor.getSelectedBlockClientId();") as? String
277+
}
278+
279+
/// Inserts a block with the given name at the current insertion point.
280+
///
281+
/// - parameter blockName: The name of the block to insert (e.g., "core/paragraph").
282+
/// - parameter selectedBlockID: Optional pre-captured selected block ID.
283+
private func insertBlock(_ blockName: String, selectedBlockID: String? = nil) {
284+
if let selectedBlockID {
285+
evaluate("editor.insertBlock('\(blockName)', '\(selectedBlockID)');")
286+
} else {
287+
evaluate("editor.insertBlock('\(blockName)');")
288+
}
289+
}
290+
266291
// MARK: - GutenbergEditorControllerDelegate
267292

268293
fileprivate func controller(_ controller: GutenbergEditorController, didReceiveMessage message: EditorJSMessage) {

src/components/editor-toolbar/index.jsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,11 @@ const EditorToolbar = ( { className } ) => {
8181
const classes = clsx( 'gutenberg-kit-editor-toolbar', className );
8282

8383
const addBlockButton = enableNativeBlockInserter ? (
84-
<ToolbarButton
84+
<Button
8585
title={ __( 'Add block' ) }
8686
icon={ plus }
87-
onClick={ () => {
88-
if ( isInserterOpened ) {
89-
setIsInserterOpened( false );
90-
}
87+
onTouchEnd={ ( e ) => {
88+
e.preventDefault();
9189
showBlockInserter();
9290
} }
9391
className="gutenberg-kit-add-block-button"

src/components/editor/use-host-bridge.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useEffect, useCallback, useRef } from '@wordpress/element';
55
import { useDispatch, useSelect } from '@wordpress/data';
66
import { store as coreStore } from '@wordpress/core-data';
77
import { store as editorStore } from '@wordpress/editor';
8-
import { parse, serialize, getBlockType } from '@wordpress/blocks';
8+
import { parse, serialize, getBlockType, createBlock } from '@wordpress/blocks';
99
import { store as blockEditorStore } from '@wordpress/block-editor';
1010
import { insert, create, toHTMLString } from '@wordpress/rich-text';
1111

@@ -21,12 +21,15 @@ export function useHostBridge( post, editorRef ) {
2121
const { undo, redo, switchEditorMode } = useDispatch( editorStore );
2222
const { getEditedPostAttribute, getEditedPostContent } =
2323
useSelect( editorStore );
24-
const { updateBlock, selectionChange } = useDispatch( blockEditorStore );
24+
const { updateBlock, selectionChange, insertBlock, replaceBlock } =
25+
useDispatch( blockEditorStore );
2526
const {
2627
getSelectedBlockClientId,
2728
getBlock,
2829
getSelectionStart,
2930
getSelectionEnd,
31+
getBlockRootClientId,
32+
getBlockIndex,
3033
} = useSelect( blockEditorStore );
3134

3235
const editContent = useCallback(
@@ -118,6 +121,44 @@ export function useHostBridge( post, editorRef ) {
118121
}
119122
};
120123

124+
window.editor.getSelectedBlockClientId = () => {
125+
return getSelectedBlockClientId();
126+
};
127+
128+
window.editor.insertBlock = (
129+
blockName,
130+
selectedBlockClientId = null
131+
) => {
132+
const targetBlockClientId =
133+
selectedBlockClientId || getSelectedBlockClientId();
134+
const block = createBlock( blockName );
135+
136+
if ( targetBlockClientId ) {
137+
const selectedBlock = getBlock( targetBlockClientId );
138+
139+
// If the selected block is an empty paragraph, replace it
140+
const isParagraph = selectedBlock?.name === 'core/paragraph';
141+
const isEmpty =
142+
! selectedBlock?.attributes?.content ||
143+
selectedBlock.attributes.content.trim() === '';
144+
145+
if ( isParagraph && isEmpty ) {
146+
replaceBlock( targetBlockClientId, block );
147+
} else {
148+
// Otherwise, insert after the currently selected block
149+
const rootClientId =
150+
getBlockRootClientId( targetBlockClientId );
151+
const blockIndex = getBlockIndex( targetBlockClientId );
152+
insertBlock( block, blockIndex + 1, rootClientId, true );
153+
}
154+
} else {
155+
// No selection, insert at the current position
156+
insertBlock( block, undefined, undefined, true );
157+
}
158+
159+
return true;
160+
};
161+
121162
window.editor.appendTextAtCursor = ( text ) => {
122163
const selectedBlockClientId = getSelectedBlockClientId();
123164

@@ -185,6 +226,8 @@ export function useHostBridge( post, editorRef ) {
185226
delete window.editor.redo;
186227
delete window.editor.switchEditorMode;
187228
delete window.editor.dismissTopModal;
229+
delete window.editor.getSelectedBlockClientId;
230+
delete window.editor.insertBlock;
188231
delete window.editor.appendTextAtCursor;
189232
};
190233
}, [
@@ -199,8 +242,12 @@ export function useHostBridge( post, editorRef ) {
199242
getBlock,
200243
getSelectionStart,
201244
getSelectionEnd,
245+
getBlockRootClientId,
246+
getBlockIndex,
202247
updateBlock,
203248
selectionChange,
249+
insertBlock,
250+
replaceBlock,
204251
] );
205252
}
206253

0 commit comments

Comments
 (0)