Native undo on iOS 13
See original GitHub issueNew tap gestures were introduced for iOS 13 which result in strange undo in TipTap. The following one could be a solution to the problem, maybe worth adding to the core as an option? Original idea found here.
import { Extension, Plugin } from 'tiptap'
import { undo, redo } from 'prosemirror-history'
export default class NativeUndo extends Extension {
get name() {
return 'nativeUndo'
}
get plugins() {
let undoMock = null
let beforeinputHandler = null
return [
new Plugin({
view(view) {
/**
* Create a hidden contenteditable element
* We perform fake actions on this element to manipulate the browser undo stack
*/
undoMock = document.createElement('div')
undoMock.setAttribute('contenteditable', 'true')
undoMock.setAttribute('style', 'position:fixed; bottom:-5em;')
document.body.insertBefore(undoMock, null)
const setSelection = range => {
const sel = window.getSelection()
const previousRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null
sel.removeAllRanges()
sel.addRange(range)
return previousRange
}
/**
* By performing a fake action on `undoMock` we force the browser to put something on its undo-stack.
* This also forces the browser to delete its redo stack.
*/
const simulateAddToUndoStack = () => {
const range = document.createRange()
range.selectNodeContents(undoMock)
const restoreRange = setSelection(range)
document.execCommand('insertText', false, 'x')
setSelection(restoreRange)
return restoreRange
}
let simulatedUndoActive = false
/**
* By performing a fake undo on `undoMock`, we force the browser to put something on its redo-stack
*/
const simulateAddToRedoStack = () => {
// Perform a fake action on undoMock. The browser will think that it can undo this action.
const restoreRange = simulateAddToUndoStack()
// wait for the next tick, and tell the browser to undo the fake action on undoMock
simulatedUndoActive = true
try {
document.execCommand('undo')
} finally {
simulatedUndoActive = false
}
// restore previous selection
setSelection(restoreRange)
}
beforeinputHandler = (event) => {
// we only handle user interactions
if (simulatedUndoActive) {
return
}
switch (event.inputType) {
case 'historyUndo':
event.preventDefault()
undo(view.state, view.dispatch)
if (undo(view.state)) {
// we can perform another undo
simulateAddToUndoStack()
}
simulateAddToRedoStack()
return true
case 'historyRedo':
event.preventDefault()
redo(view.state, view.dispatch)
if (!redo(view.state)) {
// by triggering another action, we force the browser to empty the undo stack
simulateAddToUndoStack()
} else {
simulateAddToRedoStack()
}
return true
}
return false
}
// In safari the historyUndo/Redo event is triggered on the undoMock
// In Chrome these events are triggered on the editor
undoMock.addEventListener('beforeinput', event => {
beforeinputHandler(event)
})
return {
update(view, prevState) {
},
destroy() {
removeNode(undoMock)
undoMock = null
},
}
},
props: {
handleDOMEvents: {
beforeinput(view, event) {
beforeinputHandler(event, view)
},
},
},
}),
]
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (4 by maintainers)
Top Results From Across the Web
Native undo on iOS 13 · Issue #468 · ueberdosis/tiptap - GitHub
New tap gestures were introduced for iOS 13 which result in strange undo in TipTap. The following one could be a solution to...
Read more >Detect iOS 13 undo & redo - Stack Overflow
I have a WKWebView with a custom implementation of undo and redo. I would like to be able to know when the system...
Read more >How to use 'Shake to Undo' typing on iPhone - Mashable
Shake to Undo is alive and well. But there's always the the finger swipe. ... Mistakes happen. But on the iPhone, they can...
Read more >How to undo/redo on an iPhone - PhoneArena
The first and probably most well-known way to undo typing on both iPhones and iPads is to simply shake your device. Left, right,...
Read more >Augmented Text Editing on Mobile: The New iOS 13 Gestures
To undo, swipe to left with three fingers. To redo, swipe to right with three fingers. Sheet Selection. Sometimes you may want to...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Thanks @holtwick! I’m quoting him here directly:
Closing this for now because I also think it’s a bit too hacky 😃