UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

85 lines (83 loc) 4.06 kB
import { useCallback, useEffect, useRef } from 'react'; import { ACTION, ACTION_SUBJECT, EVENT_TYPE, getAnalyticsEventsFromTransaction } from '@atlaskit/editor-common/analytics'; import { isDirtyTransaction } from '@atlaskit/editor-common/collab'; import { getDocStructure } from '@atlaskit/editor-common/core-utils'; import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures'; import { findChangedNodesFromTransaction } from '../../utils/findChangedNodesFromTransaction'; import { freezeUnsafeTransactionProperties } from '../../utils/performance/safer-transactions'; import { EVENT_NAME_ON_CHANGE } from '../../utils/performance/track-transactions'; import { validateNodes, validNode } from '../../utils/validateNodes'; export var useDispatchTransaction = function useDispatchTransaction(_ref) { var onChange = _ref.onChange, dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent, onEditorViewUpdated = _ref.onEditorViewUpdated, isRemoteReplaceDocumentTransaction = _ref.isRemoteReplaceDocumentTransaction; // We need to have a ref to the latest `onChange` since the `dispatchTransaction` gets captured var onChangeRef = useRef(onChange); useEffect(function () { onChangeRef.current = onChange; }, [onChange]); var dispatchTransaction = useCallback(function (view, unsafeTransaction) { if (!view) { return; } var nodes = findChangedNodesFromTransaction(unsafeTransaction); var changedNodesValid = validateNodes(nodes); var transaction = new Proxy(unsafeTransaction, freezeUnsafeTransactionProperties({ dispatchAnalyticsEvent: dispatchAnalyticsEvent, pluginKey: 'unknown-reacteditorview' })); // If the transaction is a remote replaceDocument transaction, we should skip validation. // Remote replaceDocument transactions are fired when the document is replaced by initialization of editor-plugin-collab-edit // If there is a discrepancy in the ProseMirror schema at initialization, it results in the editor being loaded with no content, // giving the user the impression that content has been lost var isRemoteReplace = isRemoteReplaceDocumentTransaction ? isRemoteReplaceDocumentTransaction(transaction) : false; if (changedNodesValid || isRemoteReplace) { var oldEditorState = view.state; // go ahead and update the state now we know the transaction is good var _view$state$applyTran = view.state.applyTransaction(transaction), newEditorState = _view$state$applyTran.state, transactions = _view$state$applyTran.transactions; if (newEditorState === oldEditorState) { return; } view.updateState(newEditorState); onEditorViewUpdated({ originalTransaction: transaction, transactions: transactions, oldEditorState: oldEditorState, newEditorState: newEditorState }); if (onChangeRef.current && transaction.docChanged) { var source = transaction.getMeta('isRemote') ? 'remote' : 'local'; var isDirtyChange = isDirtyTransaction(transaction); startMeasure(EVENT_NAME_ON_CHANGE); onChangeRef.current(view, { source: source, isDirtyChange: isDirtyChange }); stopMeasure(EVENT_NAME_ON_CHANGE); } } if (!changedNodesValid) { var invalidNodes = nodes.filter(function (node) { return !validNode(node); }).map(function (node) { return getDocStructure(node, { compact: true }); }); dispatchAnalyticsEvent({ action: ACTION.DISPATCHED_INVALID_TRANSACTION, actionSubject: ACTION_SUBJECT.EDITOR, eventType: EVENT_TYPE.OPERATIONAL, attributes: { analyticsEventPayloads: getAnalyticsEventsFromTransaction(transaction), invalidNodes: invalidNodes, isRemoteReplaceDocumentTransaction: isRemoteReplace } }); } }, [dispatchAnalyticsEvent, onEditorViewUpdated, isRemoteReplaceDocumentTransaction]); return dispatchTransaction; };