Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Remove old decorator fingerprint logic
Browse files Browse the repository at this point in the history
Reviewed By: mitermayer

Differential Revision: D7977136

fbshipit-source-id: e6389c58d668b8c403020bfa3f740c4f777add75
  • Loading branch information
sophiebits authored and facebook-github-bot committed May 15, 2018
1 parent 3798902 commit b2f6ed0
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
'use strict';

jest.disableAutomock();
jest.mock('gkx', () => name => name === 'draft_improved_decorator_fingerprint');

const CompositeDraftDecorator = require('CompositeDraftDecorator');
const ContentBlock = require('ContentBlock');
Expand Down
123 changes: 54 additions & 69 deletions src/component/handlers/edit/editOnBeforeInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
import type DraftEditor from 'DraftEditor.react';
import type {DraftInlineStyle} from 'DraftInlineStyle';

const BlockTree = require('BlockTree');
const DraftModifier = require('DraftModifier');
const EditorState = require('EditorState');
const UserAgent = require('UserAgent');

const getEntityKeyForSelection = require('getEntityKeyForSelection');
const gkx = require('gkx');
const isEventHandled = require('isEventHandled');
const isSelectionAtLeafStart = require('isSelectionAtLeafStart');
const nullthrows = require('nullthrows');
Expand Down Expand Up @@ -190,73 +188,60 @@ function editOnBeforeInput(
}
}
if (!mustPreventNative) {
if (gkx('draft_improved_decorator_fingerprint')) {
// Let's say we have a decorator that highlights hashtags. In many cases
// we need to prevent native behavior and rerender ourselves --
// particularly, any case *except* where the inserted characters end up
// anywhere except exactly where you put them.
//
// Using [] to denote a decorated leaf, some examples:
//
// 1. 'hi #' and append 'f'
// desired rendering: 'hi [#f]'
// native rendering would be: 'hi #f' (incorrect)
//
// 2. 'x [#foo]' and insert '#' before 'f'
// desired rendering: 'x #[#foo]'
// native rendering would be: 'x [##foo]' (incorrect)
//
// 3. '[#foobar]' and insert ' ' between 'foo' and 'bar'
// desired rendering: '[#foo] bar'
// native rendering would be: '[#foo bar]' (incorrect)
//
// 4. '[#foo]' and delete '#' [won't use this beforeinput codepath though]
// desired rendering: 'foo'
// native rendering would be: '[foo]' (incorrect)
//
// 5. '[#foo]' and append 'b'
// desired rendering: '[#foob]'
// native rendering would be: '[#foob]' (native insertion is OK here)
//
// It is safe to allow native insertion if and only if the full list of
// decorator ranges matches what we expect native insertion to give. We
// don't need to compare the content because the only possible mutation
// to consider here is inserting plain text and decorators can't affect
// text content.
const oldBlockTree = editorState.getBlockTree(anchorKey);
const newBlockTree = newEditorState.getBlockTree(anchorKey);
mustPreventNative =
oldBlockTree.size !== newBlockTree.size ||
oldBlockTree.zip(newBlockTree).some(([oldLeafSet, newLeafSet]) => {
// selectionStart is guaranteed to be selectionEnd here
const oldStart = oldLeafSet.get('start');
const adjustedStart =
oldStart + (oldStart >= selectionStart ? chars.length : 0);
const oldEnd = oldLeafSet.get('end');
const adjustedEnd =
oldEnd + (oldEnd >= selectionStart ? chars.length : 0);
return (
// Different decorators
oldLeafSet.get('decoratorKey') !== newLeafSet.get('decoratorKey') ||
// Different number of inline styles
oldLeafSet.get('leaves').size !== newLeafSet.get('leaves').size ||
// Different effective decorator position
adjustedStart !== newLeafSet.get('start') ||
adjustedEnd !== newLeafSet.get('end')
);
});
} else {
// Check the old and new "fingerprints" of the current block to determine
// whether this insertion requires any addition or removal of text nodes,
// in which case we would prevent the native character insertion.
const originalFingerprint = BlockTree.getFingerprint(
editorState.getBlockTree(anchorKey),
);
const newFingerprint = BlockTree.getFingerprint(
newEditorState.getBlockTree(anchorKey),
);
mustPreventNative = originalFingerprint !== newFingerprint;
}
// Let's say we have a decorator that highlights hashtags. In many cases
// we need to prevent native behavior and rerender ourselves --
// particularly, any case *except* where the inserted characters end up
// anywhere except exactly where you put them.
//
// Using [] to denote a decorated leaf, some examples:
//
// 1. 'hi #' and append 'f'
// desired rendering: 'hi [#f]'
// native rendering would be: 'hi #f' (incorrect)
//
// 2. 'x [#foo]' and insert '#' before 'f'
// desired rendering: 'x #[#foo]'
// native rendering would be: 'x [##foo]' (incorrect)
//
// 3. '[#foobar]' and insert ' ' between 'foo' and 'bar'
// desired rendering: '[#foo] bar'
// native rendering would be: '[#foo bar]' (incorrect)
//
// 4. '[#foo]' and delete '#' [won't use this beforeinput codepath though]
// desired rendering: 'foo'
// native rendering would be: '[foo]' (incorrect)
//
// 5. '[#foo]' and append 'b'
// desired rendering: '[#foob]'
// native rendering would be: '[#foob]' (native insertion is OK here)
//
// It is safe to allow native insertion if and only if the full list of
// decorator ranges matches what we expect native insertion to give. We
// don't need to compare the content because the only possible mutation
// to consider here is inserting plain text and decorators can't affect
// text content.
const oldBlockTree = editorState.getBlockTree(anchorKey);
const newBlockTree = newEditorState.getBlockTree(anchorKey);
mustPreventNative =
oldBlockTree.size !== newBlockTree.size ||
oldBlockTree.zip(newBlockTree).some(([oldLeafSet, newLeafSet]) => {
// selectionStart is guaranteed to be selectionEnd here
const oldStart = oldLeafSet.get('start');
const adjustedStart =
oldStart + (oldStart >= selectionStart ? chars.length : 0);
const oldEnd = oldLeafSet.get('end');
const adjustedEnd =
oldEnd + (oldEnd >= selectionStart ? chars.length : 0);
return (
// Different decorators
oldLeafSet.get('decoratorKey') !== newLeafSet.get('decoratorKey') ||
// Different number of inline styles
oldLeafSet.get('leaves').size !== newLeafSet.get('leaves').size ||
// Different effective decorator position
adjustedStart !== newLeafSet.get('start') ||
adjustedEnd !== newLeafSet.get('end')
);
});
}
if (!mustPreventNative) {
mustPreventNative = mustPreventDefaultForCharacter(chars);
Expand Down
18 changes: 0 additions & 18 deletions src/model/immutable/BlockTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,6 @@ const BlockTree = {

return List(leafSets);
},

/**
* Create a string representation of the given tree map. This allows us
* to rapidly determine whether a tree has undergone a significant
* structural change.
*/
getFingerprint: function(tree: List<DecoratorRange>): string {
return tree
.map(leafSet => {
const decoratorKey = leafSet.get('decoratorKey');
const fingerprintString =
decoratorKey !== null
? decoratorKey + '.' + (leafSet.get('end') - leafSet.get('start'))
: '';
return '' + fingerprintString + '.' + leafSet.get('leaves').size;
})
.join(FINGERPRINT_DELIMITER);
},
};

/**
Expand Down
1 change: 0 additions & 1 deletion src/model/immutable/__tests__/BlockTree-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ const assertBlockTreeGenerate = (
const tree = BlockTree.generate(content, block, decorator);

expect(tree.toJS()).toMatchSnapshot();
expect(BlockTree.getFingerprint(tree)).toMatchSnapshot();

// to remove
return tree;
Expand Down
12 changes: 0 additions & 12 deletions src/model/immutable/__tests__/__snapshots__/BlockTree-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ Array [
]
`;

exports[`must generate for styled block with empty decorator 2`] = `".3"`;

exports[`must generate for styled block with multiple decorators 1`] = `
Array [
Object {
Expand Down Expand Up @@ -72,8 +70,6 @@ Array [
]
`;

exports[`must generate for styled block with multiple decorators 2`] = `"y.3.1-.2-z.4.2"`;

exports[`must generate for styled block with single decorator 1`] = `
Array [
Object {
Expand Down Expand Up @@ -120,8 +116,6 @@ Array [
]
`;

exports[`must generate for styled block with single decorator 2`] = `".1-x.3.2-.2"`;

exports[`must generate for unstyled block with empty decorator 1`] = `
Array [
Object {
Expand All @@ -138,8 +132,6 @@ Array [
]
`;

exports[`must generate for unstyled block with empty decorator 2`] = `".1"`;

exports[`must generate for unstyled block with multiple decorators 1`] = `
Array [
Object {
Expand Down Expand Up @@ -178,8 +170,6 @@ Array [
]
`;

exports[`must generate for unstyled block with multiple decorators 2`] = `"y.3.1-.1-z.1.1"`;

exports[`must generate for unstyled block with single decorator 1`] = `
Array [
Object {
Expand Down Expand Up @@ -217,5 +207,3 @@ Array [
},
]
`;

exports[`must generate for unstyled block with single decorator 2`] = `".1-x.3.1-.1"`;

0 comments on commit b2f6ed0

Please sign in to comment.