From a27fbd8f6a40dccdf0b5208cb06a7209fab3acff Mon Sep 17 00:00:00 2001 From: iseulde Date: Fri, 9 Feb 2018 19:44:26 +0100 Subject: [PATCH] Avoid separate buffer key in history reducer --- editor/store/selectors.js | 41 ++++--- editor/store/test/reducer.js | 100 ++++++++--------- editor/store/test/selectors.js | 140 ++++++++++++------------ editor/utils/with-history/index.js | 47 ++++---- editor/utils/with-history/test/index.js | 33 +++--- 5 files changed, 175 insertions(+), 186 deletions(-) diff --git a/editor/store/selectors.js b/editor/store/selectors.js index 6b3af0a1111943..3362efb5b0a326 100644 --- a/editor/store/selectors.js +++ b/editor/store/selectors.js @@ -224,7 +224,7 @@ export function getCurrentPostLastRevisionId( state ) { * @return {Object} Object of key value pairs comprising unsaved edits. */ export function getPostEdits( state ) { - return get( state, [ 'editor', 'buffer', 'edits' ], {} ); + return get( state, [ 'editor', 'present', 'edits' ], {} ); } /** @@ -368,10 +368,9 @@ export function getDocumentTitle( state ) { * @return {string} Raw post excerpt. */ export function getEditedPostExcerpt( state ) { - const edits = getPostEdits( state ); - return edits.excerpt === undefined ? + return state.editor.present.edits.excerpt === undefined ? state.currentPost.excerpt : - edits.excerpt; + state.editor.present.edits.excerpt; } /** @@ -403,7 +402,7 @@ export function getEditedPostPreviewLink( state ) { */ export const getBlock = createSelector( ( state, uid ) => { - const block = state.editor.buffer.blocksByUid[ uid ]; + const block = state.editor.present.blocksByUid[ uid ]; if ( ! block ) { return null; } @@ -436,15 +435,15 @@ export const getBlock = createSelector( }; }, ( state ) => [ - get( state, [ 'editor', 'buffer', 'blocksByUid' ] ), - get( state, [ 'editor', 'buffer', 'edits', 'meta' ] ), + get( state, [ 'editor', 'present', 'blocksByUid' ] ), + get( state, [ 'editor', 'present', 'edits', 'meta' ] ), get( state, 'currentPost.meta' ), ] ); function getPostMeta( state, key ) { - return has( state, [ 'editor', 'buffer', 'edits', 'meta', key ] ) ? - get( state, [ 'editor', 'buffer', 'edits', 'meta', key ] ) : + return has( state, [ 'editor', 'present', 'edits', 'meta', key ] ) ? + get( state, [ 'editor', 'present', 'edits', 'meta', key ] ) : get( state, [ 'currentPost', 'meta', key ] ); } @@ -466,8 +465,8 @@ export const getBlocks = createSelector( ); }, ( state ) => [ - state.editor.buffer.blockOrder, - state.editor.buffer.blocksByUid, + state.editor.present.blockOrder, + state.editor.present.blocksByUid, ] ); @@ -526,7 +525,7 @@ export function getSelectedBlock( state ) { * @return {?string} Root UID, if exists */ export function getBlockRootUID( state, uid ) { - const { blockOrder } = state.editor.buffer; + const { blockOrder } = state.editor.present; for ( const rootUID in blockOrder ) { if ( includes( blockOrder[ rootUID ], uid ) ) { @@ -575,7 +574,7 @@ export function getAdjacentBlock( state, startUID, modifier = 1 ) { return null; } - const { blockOrder } = state.editor.buffer; + const { blockOrder } = state.editor.present; const orderSet = blockOrder[ rootUID ]; const index = orderSet.indexOf( startUID ); const nextIndex = ( index + ( 1 * modifier ) ); @@ -671,7 +670,7 @@ export const getMultiSelectedBlockUids = createSelector( return blockOrder.slice( startIndex, endIndex + 1 ); }, ( state ) => [ - state.editor.buffer.blockOrder, + state.editor.present.blockOrder, state.blockSelection.start, state.blockSelection.end, ], @@ -688,11 +687,11 @@ export const getMultiSelectedBlockUids = createSelector( export const getMultiSelectedBlocks = createSelector( ( state ) => getMultiSelectedBlockUids( state ).map( ( uid ) => getBlock( state, uid ) ), ( state ) => [ - state.editor.buffer.blockOrder, + state.editor.present.blockOrder, state.blockSelection.start, state.blockSelection.end, - state.editor.buffer.blocksByUid, - state.editor.buffer.edits.meta, + state.editor.present.blocksByUid, + state.editor.present.edits.meta, state.currentPost.meta, ] ); @@ -798,7 +797,7 @@ export function getMultiSelectedBlocksEndUid( state ) { * @return {Array} Ordered unique IDs of post blocks. */ export function getBlockOrder( state, rootUID ) { - return state.editor.buffer.blockOrder[ rootUID || '' ] || DEFAULT_BLOCK_ORDER; + return state.editor.present.blockOrder[ rootUID || '' ] || DEFAULT_BLOCK_ORDER; } /** @@ -1050,9 +1049,9 @@ export const getEditedPostContent = createSelector( return serialize( getBlocks( state ) ); }, ( state ) => [ - state.editor.buffer.edits.content, - state.editor.buffer.blocksByUid, - state.editor.buffer.blockOrder, + state.editor.present.edits.content, + state.editor.present.blocksByUid, + state.editor.present.blockOrder, ], ); diff --git a/editor/store/test/reducer.js b/editor/store/test/reducer.js index 063ea9f8514be0..839db90d213db3 100644 --- a/editor/store/test/reducer.js +++ b/editor/store/test/reducer.js @@ -72,11 +72,11 @@ describe( 'state', () => { it( 'should return history (empty edits, blocksByUid, blockOrder), dirty flag by default', () => { const state = editor( undefined, {} ); - expect( state.past ).toEqual( [] ); + expect( state.past ).toEqual( [ state.present ] ); expect( state.future ).toEqual( [] ); - expect( state.buffer.edits ).toEqual( {} ); - expect( state.buffer.blocksByUid ).toEqual( {} ); - expect( state.buffer.blockOrder ).toEqual( {} ); + expect( state.present.edits ).toEqual( {} ); + expect( state.present.blocksByUid ).toEqual( {} ); + expect( state.present.blockOrder ).toEqual( {} ); expect( state.isDirty ).toBe( false ); } ); @@ -87,9 +87,9 @@ describe( 'state', () => { blocks: [ { uid: 'bananas', innerBlocks: [] } ], } ); - expect( Object.keys( state.buffer.blocksByUid ) ).toHaveLength( 1 ); - expect( values( state.buffer.blocksByUid )[ 0 ].uid ).toBe( 'bananas' ); - expect( state.buffer.blockOrder ).toEqual( { + expect( Object.keys( state.present.blocksByUid ) ).toHaveLength( 1 ); + expect( values( state.present.blocksByUid )[ 0 ].uid ).toBe( 'bananas' ); + expect( state.present.blockOrder ).toEqual( { '': [ 'bananas' ], bananas: [], } ); @@ -105,8 +105,8 @@ describe( 'state', () => { } ], } ); - expect( Object.keys( state.buffer.blocksByUid ) ).toHaveLength( 2 ); - expect( state.buffer.blockOrder ).toEqual( { + expect( Object.keys( state.present.blocksByUid ) ).toHaveLength( 2 ); + expect( state.present.blockOrder ).toEqual( { '': [ 'bananas' ], apples: [], bananas: [ 'apples' ], @@ -132,9 +132,9 @@ describe( 'state', () => { } ], } ); - expect( Object.keys( state.buffer.blocksByUid ) ).toHaveLength( 2 ); - expect( values( state.buffer.blocksByUid )[ 1 ].uid ).toBe( 'ribs' ); - expect( state.buffer.blockOrder ).toEqual( { + expect( Object.keys( state.present.blocksByUid ) ).toHaveLength( 2 ); + expect( values( state.present.blocksByUid )[ 1 ].uid ).toBe( 'ribs' ); + expect( state.present.blockOrder ).toEqual( { '': [ 'chicken', 'ribs' ], chicken: [], ribs: [], @@ -161,10 +161,10 @@ describe( 'state', () => { } ], } ); - expect( Object.keys( state.buffer.blocksByUid ) ).toHaveLength( 1 ); - expect( values( state.buffer.blocksByUid )[ 0 ].name ).toBe( 'core/freeform' ); - expect( values( state.buffer.blocksByUid )[ 0 ].uid ).toBe( 'wings' ); - expect( state.buffer.blockOrder ).toEqual( { + expect( Object.keys( state.present.blocksByUid ) ).toHaveLength( 1 ); + expect( values( state.present.blocksByUid )[ 0 ].name ).toBe( 'core/freeform' ); + expect( values( state.present.blocksByUid )[ 0 ].uid ).toBe( 'wings' ); + expect( state.present.blockOrder ).toEqual( { '': [ 'wings' ], wings: [], } ); @@ -185,7 +185,7 @@ describe( 'state', () => { blocks: [ replacementBlock ], } ); - expect( state.buffer.blockOrder ).toEqual( { + expect( state.present.blockOrder ).toEqual( { '': [ wrapperBlock.uid ], [ wrapperBlock.uid ]: [ replacementBlock.uid ], [ replacementBlock.uid ]: [], @@ -212,7 +212,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.blocksByUid.chicken ).toEqual( { + expect( state.present.blocksByUid.chicken ).toEqual( { uid: 'chicken', name: 'core/test-block', attributes: { content: 'ribs' }, @@ -240,7 +240,7 @@ describe( 'state', () => { updatedId: 3, } ); - expect( state.buffer.blocksByUid.chicken ).toEqual( { + expect( state.present.blocksByUid.chicken ).toEqual( { uid: 'chicken', name: 'core/block', attributes: { @@ -270,7 +270,7 @@ describe( 'state', () => { uids: [ 'ribs' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs', 'chicken' ] ); + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs', 'chicken' ] ); } ); it( 'should move the nested block up', () => { @@ -287,7 +287,7 @@ describe( 'state', () => { rootUID: wrapperBlock.uid, } ); - expect( state.buffer.blockOrder ).toEqual( { + expect( state.present.blockOrder ).toEqual( { '': [ wrapperBlock.uid ], [ wrapperBlock.uid ]: [ movedBlock.uid, siblingBlock.uid ], [ movedBlock.uid ]: [], @@ -320,7 +320,7 @@ describe( 'state', () => { uids: [ 'ribs', 'veggies' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs', 'veggies', 'chicken' ] ); + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs', 'veggies', 'chicken' ] ); } ); it( 'should move multiple nested blocks up', () => { @@ -338,7 +338,7 @@ describe( 'state', () => { rootUID: wrapperBlock.uid, } ); - expect( state.buffer.blockOrder ).toEqual( { + expect( state.present.blockOrder ).toEqual( { '': [ wrapperBlock.uid ], [ wrapperBlock.uid ]: [ movedBlockA.uid, movedBlockB.uid, siblingBlock.uid ], [ movedBlockA.uid ]: [], @@ -367,7 +367,7 @@ describe( 'state', () => { uids: [ 'chicken' ], } ); - expect( state.buffer.blockOrder ).toBe( original.buffer.blockOrder ); + expect( state.present.blockOrder ).toBe( original.present.blockOrder ); } ); it( 'should move the block down', () => { @@ -390,7 +390,7 @@ describe( 'state', () => { uids: [ 'chicken' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs', 'chicken' ] ); + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs', 'chicken' ] ); } ); it( 'should move the nested block down', () => { @@ -407,7 +407,7 @@ describe( 'state', () => { rootUID: wrapperBlock.uid, } ); - expect( state.buffer.blockOrder ).toEqual( { + expect( state.present.blockOrder ).toEqual( { '': [ wrapperBlock.uid ], [ wrapperBlock.uid ]: [ siblingBlock.uid, movedBlock.uid ], [ movedBlock.uid ]: [], @@ -440,7 +440,7 @@ describe( 'state', () => { uids: [ 'chicken', 'ribs' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'veggies', 'chicken', 'ribs' ] ); + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'veggies', 'chicken', 'ribs' ] ); } ); it( 'should move multiple nested blocks down', () => { @@ -458,7 +458,7 @@ describe( 'state', () => { rootUID: wrapperBlock.uid, } ); - expect( state.buffer.blockOrder ).toEqual( { + expect( state.present.blockOrder ).toEqual( { '': [ wrapperBlock.uid ], [ wrapperBlock.uid ]: [ siblingBlock.uid, movedBlockA.uid, movedBlockB.uid ], [ movedBlockA.uid ]: [], @@ -487,7 +487,7 @@ describe( 'state', () => { uids: [ 'ribs' ], } ); - expect( state.buffer.blockOrder ).toBe( original.buffer.blockOrder ); + expect( state.present.blockOrder ).toBe( original.present.blockOrder ); } ); it( 'should remove the block', () => { @@ -510,9 +510,9 @@ describe( 'state', () => { uids: [ 'chicken' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); - expect( state.buffer.blockOrder ).not.toHaveProperty( 'chicken' ); - expect( state.buffer.blocksByUid ).toEqual( { + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); + expect( state.present.blockOrder ).not.toHaveProperty( 'chicken' ); + expect( state.present.blocksByUid ).toEqual( { ribs: { uid: 'ribs', name: 'core/test-block', @@ -546,10 +546,10 @@ describe( 'state', () => { uids: [ 'chicken', 'veggies' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); - expect( state.buffer.blockOrder ).not.toHaveProperty( 'chicken' ); - expect( state.buffer.blockOrder ).not.toHaveProperty( 'veggies' ); - expect( state.buffer.blocksByUid ).toEqual( { + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); + expect( state.present.blockOrder ).not.toHaveProperty( 'chicken' ); + expect( state.present.blockOrder ).not.toHaveProperty( 'veggies' ); + expect( state.present.blocksByUid ).toEqual( { ribs: { uid: 'ribs', name: 'core/test-block', @@ -584,8 +584,8 @@ describe( 'state', () => { } ], } ); - expect( Object.keys( state.buffer.blocksByUid ) ).toHaveLength( 3 ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'kumquat', 'persimmon', 'loquat' ] ); + expect( Object.keys( state.present.blocksByUid ) ).toHaveLength( 3 ); + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'kumquat', 'persimmon', 'loquat' ] ); } ); it( 'should remove associated blocks when deleting a reusable block', () => { @@ -609,8 +609,8 @@ describe( 'state', () => { associatedBlockUids: [ 'chicken', 'veggies' ], } ); - expect( state.buffer.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); - expect( state.buffer.blocksByUid ).toEqual( { + expect( state.present.blockOrder[ '' ] ).toEqual( [ 'ribs' ] ); + expect( state.present.blocksByUid ).toEqual( { ribs: { uid: 'ribs', name: 'core/test-block', @@ -636,7 +636,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.edits ).toEqual( { + expect( state.present.edits ).toEqual( { status: 'draft', title: 'post title', tags: [ 1 ], @@ -659,7 +659,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.edits ).toBe( original.buffer.edits ); + expect( state.present.edits ).toBe( original.present.edits ); } ); it( 'should save modified properties', () => { @@ -680,7 +680,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.edits ).toEqual( { + expect( state.present.edits ).toEqual( { status: 'draft', title: 'modified title', tags: [ 2 ], @@ -696,7 +696,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.edits ).toEqual( { + expect( state.present.edits ).toEqual( { status: 'draft', title: 'post title', } ); @@ -714,7 +714,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.edits ).toHaveProperty( 'content' ); + expect( state.present.edits ).toHaveProperty( 'content' ); state = editor( original, { type: 'RESET_BLOCKS', @@ -731,7 +731,7 @@ describe( 'state', () => { } ], } ); - expect( state.buffer.edits ).not.toHaveProperty( 'content' ); + expect( state.present.edits ).not.toHaveProperty( 'content' ); } ); } ); @@ -753,7 +753,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.blocksByUid.kumquat.attributes.updated ).toBe( true ); + expect( state.present.blocksByUid.kumquat.attributes.updated ).toBe( true ); } ); it( 'should accumulate attribute block updates', () => { @@ -775,7 +775,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.blocksByUid.kumquat.attributes ).toEqual( { + expect( state.present.blocksByUid.kumquat.attributes ).toEqual( { updated: true, moreUpdated: true, } ); @@ -794,7 +794,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.blocksByUid ).toBe( original.buffer.blocksByUid ); + expect( state.present.blocksByUid ).toBe( original.present.blocksByUid ); } ); it( 'should return with same reference if no changes in updates', () => { @@ -816,7 +816,7 @@ describe( 'state', () => { }, } ); - expect( state.buffer.blocksByUid ).toBe( state.buffer.blocksByUid ); + expect( state.present.blocksByUid ).toBe( state.present.blocksByUid ); } ); } ); } ); diff --git a/editor/store/test/selectors.js b/editor/store/test/selectors.js index 1c35b1706bb56c..c3aeed433d29a1 100644 --- a/editor/store/test/selectors.js +++ b/editor/store/test/selectors.js @@ -250,7 +250,7 @@ describe( 'selectors', () => { status: 'auto-draft', }, editor: { - buffer: { + present: { edits: {}, }, }, @@ -265,7 +265,7 @@ describe( 'selectors', () => { status: 'draft', }, editor: { - buffer: { + present: { edits: {}, }, }, @@ -387,7 +387,7 @@ describe( 'selectors', () => { const state = { currentPost: { slug: 'old slug' }, editor: { - buffer: { + present: { edits: { slug: 'new slug', }, @@ -459,7 +459,7 @@ describe( 'selectors', () => { it( 'should return the post edits', () => { const state = { editor: { - buffer: { + present: { edits: { title: 'terga' }, }, }, @@ -476,7 +476,7 @@ describe( 'selectors', () => { title: 'sassel', }, editor: { - buffer: { + present: { edits: { status: 'private' }, }, }, @@ -491,7 +491,7 @@ describe( 'selectors', () => { title: 'sassel', }, editor: { - buffer: { + present: { edits: { title: 'youcha' }, }, }, @@ -510,7 +510,7 @@ describe( 'selectors', () => { title: 'The Title', }, editor: { - buffer: { + present: { edits: {}, blocksByUid: {}, blockOrder: {}, @@ -530,7 +530,7 @@ describe( 'selectors', () => { title: 'The Title', }, editor: { - buffer: { + present: { edits: { title: 'Modified Title', }, @@ -550,7 +550,7 @@ describe( 'selectors', () => { title: '', }, editor: { - buffer: { + present: { edits: {}, blocksByUid: {}, blockOrder: {}, @@ -571,7 +571,7 @@ describe( 'selectors', () => { title: '', }, editor: { - buffer: { + present: { edits: {}, blocksByUid: {}, blockOrder: {}, @@ -592,7 +592,7 @@ describe( 'selectors', () => { excerpt: 'sassel', }, editor: { - buffer: { + present: { edits: { status: 'private' }, }, }, @@ -607,7 +607,7 @@ describe( 'selectors', () => { excerpt: 'sassel', }, editor: { - buffer: { + present: { edits: { excerpt: 'youcha' }, }, }, @@ -624,7 +624,7 @@ describe( 'selectors', () => { status: 'draft', }, editor: { - buffer: { + present: { edits: {}, }, }, @@ -639,7 +639,7 @@ describe( 'selectors', () => { status: 'private', }, editor: { - buffer: { + present: { edits: {}, }, }, @@ -655,7 +655,7 @@ describe( 'selectors', () => { password: 'chicken', }, editor: { - buffer: { + present: { edits: {}, }, }, @@ -671,7 +671,7 @@ describe( 'selectors', () => { password: 'chicken', }, editor: { - buffer: { + present: { edits: { status: 'private', password: null, @@ -833,7 +833,7 @@ describe( 'selectors', () => { it( 'should return false if the post has no title, excerpt, content', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, edits: {}, @@ -848,7 +848,7 @@ describe( 'selectors', () => { it( 'should return true if the post has a title', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, edits: {}, @@ -865,7 +865,7 @@ describe( 'selectors', () => { it( 'should return true if the post has an excerpt', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, edits: {}, @@ -882,7 +882,7 @@ describe( 'selectors', () => { it( 'should return true if the post has content', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 123: { uid: 123, @@ -909,7 +909,7 @@ describe( 'selectors', () => { it( 'should return true for posts with a future date', () => { const state = { editor: { - buffer: { + present: { edits: { date: moment().add( 7, 'days' ).format( '' ) }, }, }, @@ -921,7 +921,7 @@ describe( 'selectors', () => { it( 'should return false for posts with an old date', () => { const state = { editor: { - buffer: { + present: { edits: { date: '2016-05-30T17:21:39' }, }, }, @@ -956,7 +956,7 @@ describe( 'selectors', () => { const state = { currentPost: {}, editor: { - buffer: { + present: { blocksByUid: { 123: { uid: 123, name: 'core/paragraph', attributes: {} }, }, @@ -981,7 +981,7 @@ describe( 'selectors', () => { const state = { currentPost: {}, editor: { - buffer: { + present: { blocksByUid: {}, borderOrder: {}, edits: {}, @@ -996,7 +996,7 @@ describe( 'selectors', () => { const state = { currentPost: {}, editor: { - buffer: { + present: { blocksByUid: { 123: { uid: 123, name: 'core/paragraph', attributes: {} }, 456: { uid: 456, name: 'core/paragraph', attributes: {} }, @@ -1045,7 +1045,7 @@ describe( 'selectors', () => { }, }, editor: { - buffer: { + present: { blocksByUid: { 123: { uid: 123, name: 'core/meta-block', attributes: {} }, }, @@ -1074,7 +1074,7 @@ describe( 'selectors', () => { const state = { currentPost: {}, editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1098,7 +1098,7 @@ describe( 'selectors', () => { it( 'should return the number of top-level blocks in the post', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1116,7 +1116,7 @@ describe( 'selectors', () => { it( 'should return the number of blocks in a nested context', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 123: { uid: 123, name: 'core/columns', attributes: {} }, 456: { uid: 456, name: 'core/paragraph', attributes: {} }, @@ -1139,7 +1139,7 @@ describe( 'selectors', () => { const state = { currentPost: {}, editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1156,7 +1156,7 @@ describe( 'selectors', () => { it( 'should return null if there is multi selection', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1172,7 +1172,7 @@ describe( 'selectors', () => { it( 'should return the selected block', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1200,7 +1200,7 @@ describe( 'selectors', () => { it( 'should return null if the block does not exist', () => { const state = { editor: { - buffer: { + present: { blockOrder: {}, }, }, @@ -1212,7 +1212,7 @@ describe( 'selectors', () => { it( 'should return root UID relative the block UID', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], 123: [ 456, 56 ], @@ -1229,7 +1229,7 @@ describe( 'selectors', () => { it( 'should return empty if there is no multi selection', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], }, @@ -1244,7 +1244,7 @@ describe( 'selectors', () => { it( 'should return selected block uids if there is multi selection', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1259,7 +1259,7 @@ describe( 'selectors', () => { it( 'should return selected block uids if there is multi selection (nested context)', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], 4: [ 9, 8, 7, 6 ], @@ -1313,7 +1313,7 @@ describe( 'selectors', () => { it( 'should return the ordered block UIDs of top-level blocks by default', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], }, @@ -1327,7 +1327,7 @@ describe( 'selectors', () => { it( 'should return the ordered block UIDs at a specified rootUID', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], 123: [ 456 ], @@ -1344,7 +1344,7 @@ describe( 'selectors', () => { it( 'should return the block order', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], }, @@ -1358,7 +1358,7 @@ describe( 'selectors', () => { it( 'should return the block order (nested context)', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 23 ], 123: [ 456, 56 ], @@ -1375,7 +1375,7 @@ describe( 'selectors', () => { it( 'should return the previous block', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1398,7 +1398,7 @@ describe( 'selectors', () => { it( 'should return the previous block (nested context)', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1424,7 +1424,7 @@ describe( 'selectors', () => { it( 'should return null for the first block', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1442,7 +1442,7 @@ describe( 'selectors', () => { it( 'should return null for the first block (nested context)', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1465,7 +1465,7 @@ describe( 'selectors', () => { it( 'should return the following block', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1488,7 +1488,7 @@ describe( 'selectors', () => { it( 'should return the following block (nested context)', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1514,7 +1514,7 @@ describe( 'selectors', () => { it( 'should return null for the last block', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1532,7 +1532,7 @@ describe( 'selectors', () => { it( 'should return null for the last block (nested context)', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 23: { uid: 23, name: 'core/heading', attributes: {} }, 123: { uid: 123, name: 'core/paragraph', attributes: {} }, @@ -1582,7 +1582,7 @@ describe( 'selectors', () => { const state = { blockSelection: { start: 5, end: 3 }, editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1597,7 +1597,7 @@ describe( 'selectors', () => { const state = { blockSelection: { start: 5, end: 3 }, editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1612,7 +1612,7 @@ describe( 'selectors', () => { const state = { blockSelection: { start: 5, end: 3 }, editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1627,7 +1627,7 @@ describe( 'selectors', () => { const state = { blockSelection: {}, editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1642,7 +1642,7 @@ describe( 'selectors', () => { describe( 'isBlockMultiSelected', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1663,7 +1663,7 @@ describe( 'selectors', () => { describe( 'isFirstMultiSelectedBlock', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 5, 4, 3, 2, 1 ], }, @@ -1769,7 +1769,7 @@ describe( 'selectors', () => { end: 2, }, editor: { - buffer: { + present: { blocksByUid: { 2: { uid: 2 }, }, @@ -1793,7 +1793,7 @@ describe( 'selectors', () => { end: 2, }, editor: { - buffer: { + present: { blockOrder: { '': [ 1, 2, 3 ], }, @@ -1810,7 +1810,7 @@ describe( 'selectors', () => { preferences: { mode: 'visual' }, blockSelection: { start: null, end: null }, editor: { - buffer: { + present: { blockOrder: { '': [ 1, 2, 3 ], }, @@ -1916,7 +1916,7 @@ describe( 'selectors', () => { it( 'returns null if cannot be determined', () => { const state = { editor: { - buffer: { + present: { blockOrder: {}, blocksByUid: {}, }, @@ -1929,7 +1929,7 @@ describe( 'selectors', () => { it( 'returns null if there is more than one block in the post', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123, 456 ], }, @@ -1947,7 +1947,7 @@ describe( 'selectors', () => { it( 'returns Image if the first block is of type `core/image`', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 123 ], }, @@ -1964,7 +1964,7 @@ describe( 'selectors', () => { it( 'returns Quote if the first block is of type `core/quote`', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 456 ], }, @@ -1981,7 +1981,7 @@ describe( 'selectors', () => { it( 'returns Video if the first block is of type `core-embed/youtube`', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 567 ], }, @@ -1998,7 +1998,7 @@ describe( 'selectors', () => { it( 'returns Quote if the first block is of type `core/quote` and second is of type `core/paragraph`', () => { const state = { editor: { - buffer: { + present: { blockOrder: { '': [ 456, 789 ], }, @@ -2031,7 +2031,7 @@ describe( 'selectors', () => { it( 'should list all non-private regular block types', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, }, @@ -2048,7 +2048,7 @@ describe( 'selectors', () => { it( 'should properly list a regular block type', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, }, @@ -2075,7 +2075,7 @@ describe( 'selectors', () => { it( 'should set isDisabled when a regular block type with useOnce has been used', () => { const state = { editor: { - buffer: { + present: { blocksByUid: { 1: { uid: 1, name: 'core/test-block', attributes: {} }, }, @@ -2096,7 +2096,7 @@ describe( 'selectors', () => { it( 'should properly list reusable blocks', () => { const state = { editor: { - buffer: { + present: { blocksByUid: {}, blockOrder: {}, }, @@ -2155,7 +2155,7 @@ describe( 'selectors', () => { ], }, editor: { - buffer: { + present: { blockOrder: [], }, }, @@ -2186,7 +2186,7 @@ describe( 'selectors', () => { ], }, editor: { - buffer: { + present: { blockOrder: [], }, }, diff --git a/editor/utils/with-history/index.js b/editor/utils/with-history/index.js index c34c09fcda1b1b..047eb6d65ef9e2 100644 --- a/editor/utils/with-history/index.js +++ b/editor/utils/with-history/index.js @@ -14,40 +14,41 @@ import { includes } from 'lodash'; * @return {Function} Enhanced reducer. */ export default function withHistory( reducer, options = {} ) { + const initialPresent = reducer( undefined, {} ); + const initialState = { - past: [], - present: reducer( undefined, {} ), - buffer: reducer( undefined, {} ), + // Past already contains record of present since changes are buffered in present. + past: [ initialPresent ], + present: initialPresent, future: [], }; return ( state = initialState, action ) => { - const { past, present, buffer, future } = state; + const { past, present, future } = state; switch ( action.type ) { case 'UNDO': // If there are changes in buffer, push buffer to the future. - if ( present !== buffer ) { + if ( past[ past.length - 1 ] !== present ) { return { - past: past.slice( 0, past.length - 1 ), - present, - buffer: present, - future: [ buffer, ...future ], + past, + present: past[ past.length - 1 ], + future: [ present, ...future ], }; } // Can't undo if no past. - if ( ! past.length ) { + // If the present "buffer" is the same as the last record, + // There is no further past. + if ( past.length < 2 ) { return state; } return { past: past.slice( 0, past.length - 1 ), - present: past[ past.length - 1 ], - buffer: past[ past.length - 1 ], + present: past[ past.length - 2 ], future: [ present, ...future ], }; - case 'REDO': // Can't redo if no future. if ( ! future.length ) { @@ -55,45 +56,41 @@ export default function withHistory( reducer, options = {} ) { } return { - past: [ ...past, present ], + past: [ ...past, future[ 0 ] ], present: future[ 0 ], - buffer: future[ 0 ], future: future.slice( 1 ), }; case 'CREATE_UNDO_LEVEL': // Already has this level. - if ( present === buffer ) { + if ( past[ past.length - 1 ] === present ) { return state; } return { past: [ ...past, present ], - present: buffer, - buffer, + present, future: [], }; } - const nextBuffer = reducer( buffer, action ); + const nextPresent = reducer( present, action ); if ( includes( options.resetTypes, action.type ) ) { return { - past: [], - present: nextBuffer, - buffer: nextBuffer, + past: [ nextPresent ], + present: nextPresent, future: [], }; } - if ( buffer === nextBuffer ) { + if ( present === nextPresent ) { return state; } return { past, - present, - buffer: nextBuffer, + present: nextPresent, future, }; }; diff --git a/editor/utils/with-history/test/index.js b/editor/utils/with-history/test/index.js index b6c507c109a8a8..3cf9f88a3d0688 100644 --- a/editor/utils/with-history/test/index.js +++ b/editor/utils/with-history/test/index.js @@ -13,14 +13,13 @@ describe( 'withHistory', () => { expect( typeof reducer ).toBe( 'function' ); expect( reducer( undefined, {} ) ).toEqual( { - past: [], + past: [ { count: 0 } ], present: { count: 0 }, - buffer: { count: 0 }, future: [], } ); } ); - it( 'should track changes in buffer', () => { + it( 'should track changes in present', () => { const reducer = withHistory( counter ); let state; @@ -28,9 +27,8 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'INCREMENT' } ); expect( state ).toEqual( { - past: [], - present: { count: 0 }, - buffer: { count: 1 }, + past: [ { count: 0 } ], + present: { count: 1 }, future: [], } ); } ); @@ -44,9 +42,8 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'CREATE_UNDO_LEVEL' } ); expect( state ).toEqual( { - past: [ { count: 0 } ], + past: [ { count: 0 }, { count: 1 } ], present: { count: 1 }, - buffer: { count: 1 }, future: [], } ); @@ -62,17 +59,16 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'UNDO' } ); expect( state ).toEqual( { - past: [], + past: [ { count: 0 } ], present: { count: 0 }, - buffer: { count: 0 }, future: [ { count: 1 } ], } ); - expect( state.present ).toBe( state.buffer ); + expect( state.past[ state.past.length - 1 ] ).toBe( state.present ); expect( state ).toBe( reducer( state, { type: 'UNDO' } ) ); } ); - it( 'should perform undo of present level', () => { + it( 'should perform undo of last level', () => { const reducer = withHistory( counter ); let state; @@ -82,13 +78,12 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'UNDO' } ); expect( state ).toEqual( { - past: [], + past: [ { count: 0 } ], present: { count: 0 }, - buffer: { count: 0 }, future: [ { count: 1 } ], } ); - expect( state.present ).toBe( state.buffer ); + expect( state.past[ state.past.length - 1 ] ).toBe( state.present ); expect( state ).toBe( reducer( state, { type: 'UNDO' } ) ); } ); @@ -103,13 +98,12 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'REDO' } ); expect( state ).toEqual( { - past: [ { count: 0 } ], + past: [ { count: 0 }, { count: 1 } ], present: { count: 1 }, - buffer: { count: 1 }, future: [], } ); - expect( state.present ).toBe( state.buffer ); + expect( state.past[ state.past.length - 1 ] ).toBe( state.present ); expect( state ).toBe( reducer( state, { type: 'REDO' } ) ); } ); @@ -123,9 +117,8 @@ describe( 'withHistory', () => { state = reducer( state, { type: 'RESET_HISTORY' } ); expect( state ).toEqual( { - past: [], + past: [ { count: 1 } ], present: { count: 1 }, - buffer: { count: 1 }, future: [], } ); } );