You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Feature request] Imperative undo/redo API for iOS & Android (with canUndo/canRedo state)
Is your feature request related to a problem? Please describe.
I'm building a note-taking app on EnrichedTextInput and there is currently no way to offer undo/redo toolbar buttons on mobile:
EnrichedTextInputInstance exposes no undo() / redo() methods.
OnChangeStateEvent has no canUndo / canRedo flags, so a toolbar can't enable/disable the buttons.
Web already supports undo/redo since #622 via @tiptap/extension-history, but only through keyboard shortcuts — there is no imperative API on any platform, and mobile has no history at all. #429 asked for this earlier but was closed for inactivity, so I'd like to pick it up properly.
Today the only workaround is an app-level snapshot stack (debounced getHTML() + setValue() restore), which loses selection, fights the keyboard, and duplicates work the platform can do natively.
Describe the solution you'd like
I'd like to contribute this myself and want to align on the API before opening PRs. Proposal:
1. Imperative methods on EnrichedTextInputInstance:
/** Undoes the last user edit (typing, formatting, link/image insertion). No-op when history is empty. */
undo: ()=>void;/** Re-applies the most recently undone edit. No-op when there is nothing to redo. */
redo: ()=>void;
2. History state on OnChangeStateEvent:
canUndo: boolean;
canRedo: boolean;
Flat booleans rather than the { isActive, isConflicting, isBlocking } shape, since undo isn't a text style — alignment: string is the existing flat-field precedent. Happy to emit these via a separate event instead if you prefer to keep OnChangeStateEvent style-only.
3. Semantics:
All user-originated edits are undoable: typing, toggle* formatting, setLink / setImage / setMention.
Programmatic setValue()clears the history stack — loading content into the editor must not be undoable into an empty editor.
4. Platform notes:
iOS: plan to build on the text view's native NSUndoManager, so shake-to-undo, the three-finger gestures, and hardware-keyboard Cmd+Z stay consistent with the imperative API for free. If the editor's attributed-string mutations turn out not to register cleanly with the undo manager, fall back to a snapshot/command stack.
Android: no built-in undo manager on EditText, so this would be a Kotlin-side history stack.
Web: thin wiring of the same API onto the already-merged TipTap history (editor.commands.undo() / editor.can().undo()), closing the parity gap with the shortcuts added in feat(web): undo, redo #622.
Delivery: split by platform following the repo's existing pattern (feat(ios): …, then feat(android): …), each with Maestro flows (undo after typing, undo after formatting, setValue reset) and example-app toolbar buttons.
Describe alternatives you've considered
App-level snapshot undo (getHTML() + setValue()): works but loses selection/caret, creates large string churn on every keystroke, and can't integrate with OS-level undo gestures.
Keyboard-shortcut-only parity with web: hardware Cmd+Z already partially works on iOS, but on-screen toolbar buttons are the primary mobile UX and need both the imperative calls and the canUndo/canRedo state.
Exposing only methods without state flags: forces apps to track dirty state themselves and still mis-renders button enablement after undo-to-initial-state.
[Feature request] Imperative undo/redo API for iOS & Android (with
canUndo/canRedostate)Is your feature request related to a problem? Please describe.
I'm building a note-taking app on
EnrichedTextInputand there is currently no way to offer undo/redo toolbar buttons on mobile:EnrichedTextInputInstanceexposes noundo()/redo()methods.OnChangeStateEventhas nocanUndo/canRedoflags, so a toolbar can't enable/disable the buttons.Web already supports undo/redo since #622 via
@tiptap/extension-history, but only through keyboard shortcuts — there is no imperative API on any platform, and mobile has no history at all. #429 asked for this earlier but was closed for inactivity, so I'd like to pick it up properly.Today the only workaround is an app-level snapshot stack (debounced
getHTML()+setValue()restore), which loses selection, fights the keyboard, and duplicates work the platform can do natively.Describe the solution you'd like
I'd like to contribute this myself and want to align on the API before opening PRs. Proposal:
1. Imperative methods on
EnrichedTextInputInstance:2. History state on
OnChangeStateEvent:Flat booleans rather than the
{ isActive, isConflicting, isBlocking }shape, since undo isn't a text style —alignment: stringis the existing flat-field precedent. Happy to emit these via a separate event instead if you prefer to keepOnChangeStateEventstyle-only.3. Semantics:
toggle*formatting,setLink/setImage/setMention.setValue()clears the history stack — loading content into the editor must not be undoable into an empty editor.4. Platform notes:
NSUndoManager, so shake-to-undo, the three-finger gestures, and hardware-keyboard Cmd+Z stay consistent with the imperative API for free. If the editor's attributed-string mutations turn out not to register cleanly with the undo manager, fall back to a snapshot/command stack.EditText, so this would be a Kotlin-side history stack.editor.commands.undo()/editor.can().undo()), closing the parity gap with the shortcuts added in feat(web): undo, redo #622.Delivery: split by platform following the repo's existing pattern (
feat(ios): …, thenfeat(android): …), each with Maestro flows (undo after typing, undo after formatting,setValuereset) and example-app toolbar buttons.Describe alternatives you've considered
getHTML()+setValue()): works but loses selection/caret, creates large string churn on every keystroke, and can't integrate with OS-level undo gestures.canUndo/canRedostate.Additional context