Skip to content
Open
Changes from 1 commit
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
48 changes: 47 additions & 1 deletion src/components/PressThisEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
useEffect,
useRef,
} from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { parse } from '@wordpress/blocks';
import {
BlockEditorProvider,
Expand Down Expand Up @@ -276,6 +276,52 @@ export default function PressThisEditor( {
const [ isLoadingTags, setIsLoadingTags ] = useState( false );
const tagSearchTimeout = useRef( null );

// Undo/Redo keyboard shortcuts.
// BlockEditorKeyboardShortcuts handles block-level shortcuts but not undo/redo.
// In full Gutenberg, EditorKeyboardShortcuts from @wordpress/editor registers these,
// but Press This uses BlockEditorProvider directly.
const { undo, redo } = useDispatch( blockEditorStore );

useEffect( () => {
function handleKeyDown( event ) {
// Don't override native undo in regular form fields (title, URL input, etc.).
const tagName = event.target.tagName.toLowerCase();
if (
tagName === 'input' ||
tagName === 'textarea' ||
tagName === 'select'
) {
return;
}

const isModKey = event.ctrlKey || event.metaKey;
if ( ! isModKey ) {
return;
}

const key = event.key.toLowerCase();

// Ctrl+Z / Cmd+Z = Undo, Ctrl+Shift+Z / Cmd+Shift+Z = Redo.
if ( key === 'z' ) {
event.preventDefault();
if ( event.shiftKey ) {
redo();
} else {
undo();
}
}

// Ctrl+Y / Cmd+Y = Redo (Windows/Linux convention).
if ( key === 'y' && ! event.shiftKey ) {
event.preventDefault();
redo();
}
}

document.addEventListener( 'keydown', handleKeyDown );
return () => document.removeEventListener( 'keydown', handleKeyDown );
}, [ undo, redo ] );

// Parse initial content.
useEffect( () => {
if ( post.content ) {
Comment on lines 379 to 381
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

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

The initial content parsing (line 381) doesn't create an undo level. This means the initial parsed blocks won't be on the undo stack. While this is probably intentional for initial load, it creates an inconsistency with the pendingScrape handling (lines 400-406) which does create an undo level. Consider whether initial content should also create an undo level, or document why this difference exists.

Copilot uses AI. Check for mistakes.
Expand Down