Expose useOutlineHistory in sync + allow external state (#927)

This commit is contained in:
Dominic Gannaway
2021-11-30 18:33:06 +00:00
committed by acywatson
parent 32eeeeb282
commit 302af329c4
6 changed files with 59 additions and 28 deletions

View File

@ -48,6 +48,7 @@ module.name_mapper='^outline-react/useOutlineIsBlank' -> '<PROJECT_ROOT>/package
module.name_mapper='^outline-react/useOutlineIsTextContentEmpty' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineIsTextContentEmpty.js'
module.name_mapper='^outline-react/useOutlineCanShowPlaceholder' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineCanShowPlaceholder.js'
module.name_mapper='^outline-react/useOutlineCharacterLimit' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineCharacterLimit.js'
module.name_mapper='^outline-react/useOutlineHistory' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineHistory.js'
module.name_mapper='^outline-yjs$' -> '<PROJECT_ROOT>/packages/outline-yjs/src/index.js'

View File

@ -44,6 +44,7 @@ module.exports = {
'outline-react/dist/useOutlineCanShowPlaceholder',
'outline-react/useOutlineCharacterLimit':
'outline-react/dist/useOutlineCharacterLimit',
'outline-react/useOutlineHistory': 'outline-react/dist/useOutlineHistory',
//Shared
'shared/environment': 'shared/dist/environment',
'shared/useLayoutEffect': 'shared/dist/useLayoutEffect',

View File

@ -23,6 +23,17 @@ const MERGE = 0;
const NO_MERGE = 1;
const DISCARD = 2;
export type HistoryStateEntry = {
editor: OutlineEditor,
editorState: EditorState,
};
export type HistoryState = {
current: null | HistoryStateEntry,
redoStack: Array<HistoryStateEntry>,
undoStack: Array<HistoryStateEntry>,
};
function getDirtyNodes(
editorState: EditorState,
dirtyLeavesSet: Set<NodeKey>,
@ -130,18 +141,13 @@ function getMergeAction(
return NO_MERGE;
}
export default function useOutlineHistory(editor: OutlineEditor): () => void {
const historyState: {
current: null | EditorState,
redoStack: Array<EditorState>,
undoStack: Array<EditorState>,
} = useMemo(
() => ({
current: null,
redoStack: [],
undoStack: [],
}),
[],
export function useOutlineHistory(
editor: OutlineEditor,
externalHistoryState?: HistoryState,
): () => void {
const historyState: HistoryState = useMemo(
() => externalHistoryState || createEmptyHistoryState(),
[externalHistoryState],
);
useEffect(() => {
@ -149,12 +155,13 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
const current = historyState.current;
const redoStack = historyState.redoStack;
const undoStack = historyState.undoStack;
const currentEditorState = current === null ? null : current.editorState;
if (editorState === current) {
if (current !== null && editorState === currentEditorState) {
return;
}
const mergeAction = getMergeAction(
current,
currentEditorState,
editorState,
dirtyLeaves,
dirtyBlocks,
@ -171,7 +178,10 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
return;
}
// Else we merge
historyState.current = editorState;
historyState.current = {
editor,
editorState,
};
};
const undo = () => {
@ -184,9 +194,9 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
if (current !== null) {
redoStack.push(current);
}
const editorState = undoStack.pop();
historyState.current = editorState;
editor.setEditorState(editorState);
const historyStateEntry = undoStack.pop();
historyState.current = historyStateEntry;
historyStateEntry.editor.setEditorState(historyStateEntry.editorState);
}
};
@ -199,9 +209,9 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
if (current !== null) {
undoStack.push(current);
}
const editorState = redoStack.pop();
historyState.current = editorState;
editor.setEditorState(editorState);
const historyStateEntry = redoStack.pop();
historyState.current = historyStateEntry;
historyStateEntry.editor.setEditorState(historyStateEntry.editorState);
}
};
@ -209,6 +219,7 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
if (editor.isComposing()) {
return;
}
if (isUndo(event)) {
event.preventDefault();
event.stopPropagation();
@ -266,3 +277,11 @@ export default function useOutlineHistory(editor: OutlineEditor): () => void {
return clearHistory;
}
export function createEmptyHistoryState(): HistoryState {
return {
current: null,
redoStack: [],
undoStack: [],
};
}

View File

@ -8,15 +8,19 @@
*/
import type {OutlineEditor} from 'outline';
import type {HistoryState} from './useOutlineHistory';
import {useCallback} from 'react';
import usePlainTextSetup from './shared/usePlainTextSetup';
import useOutlineHistory from './shared/useOutlineHistory';
import {useOutlineHistory} from './useOutlineHistory';
export default function useOutlinePlainText(editor: OutlineEditor): () => void {
export default function useOutlinePlainText(
editor: OutlineEditor,
externalHistoryState?: HistoryState,
): () => void {
const clearEditor = usePlainTextSetup(editor, true);
const clearHistory = useOutlineHistory(editor);
const clearHistory = useOutlineHistory(editor, externalHistoryState);
return useCallback(
(callbackFn?: () => void) => {

View File

@ -8,15 +8,19 @@
*/
import type {OutlineEditor} from 'outline';
import type {HistoryState} from './useOutlineHistory';
import {useCallback} from 'react';
import {useRichTextSetup} from './shared/useRichTextSetup';
import useOutlineHistory from './shared/useOutlineHistory';
import {useOutlineHistory} from './useOutlineHistory';
export default function useOutlineRichText(editor: OutlineEditor): () => void {
export default function useOutlineRichText(
editor: OutlineEditor,
externalHistoryState?: HistoryState,
): () => void {
const clearEditor = useRichTextSetup(editor, true);
const clearHistory = useOutlineHistory(editor);
const clearHistory = useOutlineHistory(editor, externalHistoryState);
return useCallback(
(callbackFn?: () => void) => {

View File

@ -310,8 +310,10 @@ outlineReactModules.forEach((outlineReactModule) => {
// modules already.
if (
outlineReactModule === 'OutlineEnv' ||
outlineReactModule === 'useOutlineHistory' ||
outlineReactModule === 'useOutlineDragonSupport' ||
outlineReactModule === 'usePlainTextSetup' ||
outlineReactModule === 'useRichTextSetup' ||
outlineReactModule === 'useYjsCollaboration' ||
outlineReactModule === 'OutlineReactUtils'
) {
return;