-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update android restoreDOM to allow partial dom restoring
- Loading branch information
Showing
11 changed files
with
164 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'slate-react': patch | ||
--- | ||
|
||
Update android restoreDOM to use partial dom restoring |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 0 additions & 14 deletions
14
packages/slate-react/src/components/android/restore-dom.ts
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
packages/slate-react/src/components/android/use-restore-dom.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import React, { useCallback, useEffect, useRef } from 'react' | ||
import { Node as SlateNode, Path } from 'slate' | ||
import { ReactEditor, useSlateStatic } from '../..' | ||
import { DOMNode, isDOMElement } from '../../utils/dom' | ||
import { ELEMENT_TO_NODE, NODE_TO_RESTORE_DOM } from '../../utils/weak-maps' | ||
import { useMutationObserver } from './use-mutation-observer' | ||
|
||
const MUTATION_OBSERVER_CONFIG: MutationObserverInit = { | ||
childList: true, | ||
characterData: true, | ||
subtree: true, | ||
} | ||
|
||
function findClosestKnowSlateNode(domNode: DOMNode): SlateNode | null { | ||
let domEl = isDOMElement(domNode) ? domNode : domNode.parentElement | ||
|
||
if (domEl && !domEl.hasAttribute('data-slate-node')) { | ||
domEl = domEl.closest(`[data-slate-node]`) | ||
} | ||
|
||
const slateNode = domEl && ELEMENT_TO_NODE.get(domEl as HTMLElement) | ||
if (slateNode) { | ||
return slateNode | ||
} | ||
|
||
// Unknown dom element with a slate-slate-node attribute => the IME | ||
// most likely duplicated the node so we have to restore the parent | ||
return domEl?.parentElement | ||
? findClosestKnowSlateNode(domEl.parentElement) | ||
: null | ||
} | ||
|
||
export function useRestoreDom( | ||
node: React.RefObject<HTMLElement>, | ||
receivedUserInput: React.RefObject<boolean> | ||
) { | ||
const editor = useSlateStatic() | ||
const mutatedNodes = useRef<Set<SlateNode>>(new Set()) | ||
|
||
const handleDOMMutation = useCallback((mutations: MutationRecord[]) => { | ||
if (!receivedUserInput.current && false) { | ||
return | ||
} | ||
|
||
mutations.forEach(({ target }) => { | ||
const slateNode = findClosestKnowSlateNode(target) | ||
if (!slateNode) { | ||
return | ||
} | ||
|
||
return mutatedNodes.current.add(slateNode) | ||
}) | ||
}, []) | ||
|
||
useMutationObserver(node, handleDOMMutation, MUTATION_OBSERVER_CONFIG) | ||
|
||
useEffect(() => { | ||
// Clear mutated nodes on every render | ||
mutatedNodes.current.clear() | ||
}) | ||
|
||
const restore = useCallback(() => { | ||
const mutated = Array.from(mutatedNodes.current.values()) | ||
|
||
// Filter out child nodes of nodes that will be restored anyway | ||
const nodesToRestore = mutated.filter( | ||
n => | ||
!mutated.some(m => | ||
Path.isParent( | ||
ReactEditor.findPath(editor, m), | ||
ReactEditor.findPath(editor, n) | ||
) | ||
) | ||
) | ||
|
||
nodesToRestore.forEach(n => { | ||
// Force node to re-render | ||
NODE_TO_RESTORE_DOM.get(n)?.() | ||
}) | ||
}, []) | ||
|
||
return restore | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { useEffect, useRef, useState } from 'react' | ||
import { Node as SlateNode } from 'slate' | ||
import { NODE_TO_RESTORE_DOM } from '../utils/weak-maps' | ||
|
||
export function useContentKey(node: SlateNode) { | ||
const contentKeyRef = useRef<number>(0) | ||
const updateTimeoutRef = useRef<ReturnType<typeof setTimeout>>() | ||
|
||
const [, setForceRerenderCounter] = useState(0) | ||
|
||
useEffect(() => { | ||
NODE_TO_RESTORE_DOM.set(node, () => { | ||
// Only force a re-render if the component isn't re-rendered this tick in order | ||
// to avoid rendering it twice. | ||
updateTimeoutRef.current = setTimeout(() => { | ||
setForceRerenderCounter(state => state + 1) | ||
updateTimeoutRef.current = undefined | ||
}, 0) | ||
|
||
contentKeyRef.current++ | ||
}) | ||
|
||
return () => { | ||
NODE_TO_RESTORE_DOM.delete(node) | ||
} | ||
}, [node]) | ||
|
||
useEffect(() => { | ||
if (updateTimeoutRef.current) { | ||
clearTimeout(updateTimeoutRef.current) | ||
updateTimeoutRef.current = undefined | ||
} | ||
}) | ||
|
||
return contentKeyRef.current | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters