-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix inconsistent Link UI in Nav block list view editor #50774
Changes from 12 commits
2ae86a7
fd385b8
7d10355
b3fa26c
040ef15
3289877
9f6b8e0
836504b
3796974
a8d3c7b
6afee4d
0ad0df7
8e116ee
8f45485
8c6122c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ import { | |
useRef, | ||
useReducer, | ||
forwardRef, | ||
useState, | ||
} from '@wordpress/element'; | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
|
@@ -128,6 +129,9 @@ function ListViewComponent( | |
const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] ); | ||
|
||
const isMounted = useRef( false ); | ||
|
||
const [ insertedBlock, setInsertedBlock ] = useState( null ); | ||
|
||
const { setSelectedTreeId } = useListViewExpandSelectedItem( { | ||
firstSelectedBlockClientId: selectedClientIds[ 0 ], | ||
setExpandedState, | ||
|
@@ -212,6 +216,8 @@ function ListViewComponent( | |
BlockSettingsMenu, | ||
listViewInstanceId: instanceId, | ||
renderAdditionalBlockUI, | ||
insertedBlock, | ||
setInsertedBlock, | ||
} ), | ||
[ | ||
draggedClientIds, | ||
|
@@ -221,6 +227,8 @@ function ListViewComponent( | |
BlockSettingsMenu, | ||
instanceId, | ||
renderAdditionalBlockUI, | ||
insertedBlock, | ||
setInsertedBlock, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are stuffing even more stuff into context. Is that a problem? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's always a potential problem for performance because if the context changes and components which consume it (or their children) will be re-rendered. The setter is stable, but the However, pre-optimising context is challenging. Better to include in the |
||
] | ||
); | ||
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,7 @@ import { | |
__experimentalHeading as Heading, | ||
Spinner, | ||
} from '@wordpress/components'; | ||
import { useSelect } from '@wordpress/data'; | ||
import { useState, useEffect } from '@wordpress/element'; | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { __, sprintf } from '@wordpress/i18n'; | ||
|
||
/** | ||
|
@@ -26,7 +25,6 @@ import useNavigationMenu from '../use-navigation-menu'; | |
import LeafMoreMenu from './leaf-more-menu'; | ||
import { updateAttributes } from '../../navigation-link/update-attributes'; | ||
import { LinkUI } from '../../navigation-link/link-ui'; | ||
import { useInsertedBlock } from '../../navigation-link/use-inserted-block'; | ||
|
||
/* translators: %s: The name of a menu. */ | ||
const actionLabel = __( "Switch to '%s'" ); | ||
|
@@ -54,40 +52,13 @@ const MainContent = ( { | |
[ clientId ] | ||
); | ||
|
||
const [ clientIdWithOpenLinkUI, setClientIdWithOpenLinkUI ] = useState(); | ||
const { lastInsertedBlockClientId } = useSelect( ( select ) => { | ||
const { getLastInsertedBlocksClientIds } = unlock( | ||
select( blockEditorStore ) | ||
); | ||
const lastInsertedBlocksClientIds = getLastInsertedBlocksClientIds(); | ||
return { | ||
lastInsertedBlockClientId: | ||
lastInsertedBlocksClientIds && lastInsertedBlocksClientIds[ 0 ], | ||
}; | ||
}, [] ); | ||
const { updateBlockAttributes } = useDispatch( blockEditorStore ); | ||
|
||
const { | ||
insertedBlockAttributes, | ||
insertedBlockName, | ||
setInsertedBlockAttributes, | ||
} = useInsertedBlock( lastInsertedBlockClientId ); | ||
|
||
const hasExistingLinkValue = insertedBlockAttributes?.url; | ||
|
||
useEffect( () => { | ||
if ( | ||
lastInsertedBlockClientId && | ||
BLOCKS_WITH_LINK_UI_SUPPORT?.includes( insertedBlockName ) && | ||
! hasExistingLinkValue // don't re-show the Link UI if the block already has a link value. | ||
) { | ||
setClientIdWithOpenLinkUI( lastInsertedBlockClientId ); | ||
} | ||
}, [ | ||
lastInsertedBlockClientId, | ||
clientId, | ||
insertedBlockName, | ||
hasExistingLinkValue, | ||
] ); | ||
const setInsertedBlockAttributes = | ||
( _insertedBlockClientId ) => ( _updatedAttributes ) => { | ||
if ( ! _insertedBlockClientId ) return; | ||
updateBlockAttributes( _insertedBlockClientId, _updatedAttributes ); | ||
}; | ||
|
||
const { navigationMenu } = useNavigationMenu( currentMenuId ); | ||
|
||
|
@@ -109,23 +80,45 @@ const MainContent = ( { | |
'You have not yet created any menus. Displaying a list of your Pages' | ||
); | ||
|
||
const renderLinkUI = ( block ) => { | ||
const renderLinkUI = ( | ||
currentBlock, | ||
lastInsertedBlock, | ||
setLastInsertedBlock | ||
) => { | ||
const blockHasExistingLinkValue = !! lastInsertedBlock?.url; | ||
const blockSupportsLinkUI = BLOCKS_WITH_LINK_UI_SUPPORT?.includes( | ||
lastInsertedBlock?.name | ||
); | ||
const currentBlockWasJustInserted = | ||
lastInsertedBlock?.clientId === currentBlock.clientId; | ||
|
||
const shouldShowLinkUIForBlock = | ||
blockSupportsLinkUI && | ||
! blockHasExistingLinkValue && // don't re-show the Link UI if the block already has a link value. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this check necessary? If it only appears after a user has inserted the block, it should never have a link, right? If so, I think we can remove all the checks for if there's a link or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeh you could be right there. Have you got time to test that and commit as it's nearly my EOD? |
||
currentBlockWasJustInserted; | ||
|
||
return ( | ||
clientIdWithOpenLinkUI === block.clientId && ( | ||
shouldShowLinkUIForBlock && ( | ||
<LinkUI | ||
clientId={ lastInsertedBlockClientId } | ||
link={ insertedBlockAttributes } | ||
onClose={ () => setClientIdWithOpenLinkUI( null ) } | ||
clientId={ lastInsertedBlock?.clientId } | ||
link={ lastInsertedBlock?.attributes } | ||
onClose={ () => { | ||
setLastInsertedBlock( null ); | ||
} } | ||
hasCreateSuggestion={ false } | ||
onChange={ ( updatedValue ) => { | ||
updateAttributes( | ||
updatedValue, | ||
setInsertedBlockAttributes, | ||
insertedBlockAttributes | ||
setInsertedBlockAttributes( | ||
lastInsertedBlock?.clientId | ||
), | ||
lastInsertedBlock?.attributes | ||
); | ||
setClientIdWithOpenLinkUI( null ); | ||
setLastInsertedBlock( null ); | ||
} } | ||
onCancel={ () => { | ||
setLastInsertedBlock( null ); | ||
} } | ||
onCancel={ () => setClientIdWithOpenLinkUI( null ) } | ||
/> | ||
) | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This now forms part of the API of
renderAdditionalBlockUI
as positional params. If and whenrenderAdditionalBlockUI
becomes part of the stable API,insertedBlock
andsetInsertedBlock
might not be applicable for some use cases, but we also might want to add additional params at some stage. Would it be worth switchingrenderAdditionalBlockUI
to use an object as its param?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback on this. When I implemented this I also considered that but (for a reasons I can't recall) neglected to include it in the PR 😕
I think it's a good idea. The useful state that might need to be made available to this render prop in future might be many things so we should convert to object.
As for using a component - that seems logical to me. This PR didn't implement that but it's definitely worth calling out. It's very similar to the
renderAppender
arg ofInnerBlocks
so we could follow the pattern set down there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Thanks for opening up the follow-up issue!