Skip to content
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

Shuffle blocks for contentOnly patterns #45618

Closed
wants to merge 3 commits into from
Closed

Conversation

kevin940726
Copy link
Member

@kevin940726 kevin940726 commented Nov 9, 2022

What?

A potential approach to #44581

Note
Code isn't optimized. Once we are fine with the approach, I'll try to polish it more.

Why?

See #44581

How?

This PR implements an approach to swap non-content blocks with something else in other patterns. Since that inserted patterns don't have any information about which patterns they're inserted from, we have to perform an algorithm to "guess" which candidate patterns are alike. The algo used in this PR is to:

  1. Flatten all blocks and inner blocks in the patterns.
  2. Keep only the blocks that have __experimentalRole="content" in any of their attributes.
  3. Compare the names of the flattened content blocks to the available patterns using the same method.
  4. If both have the same length of content blocks then it's a match.

Once we find a match, we then add the "Shuffle" button to the toolbar. If the user clicks the button, it will randomly choose a pattern from the list and apply all but the contents to the blocks.

To prevent choosing the same pattern that it's added from, we do an areBlocksAlike check to see if the blocks look like existing patterns and filter it out.

Testing Instructions

  1. Insert a pattern.
  2. Go to the Code Editor and add "templateLock":"contentOnly" to the top-most group of the inserted pattern.
  3. Select the inserted pattern/group.
  4. Click on the "Shuffle" button in the toolbar.
  5. The pattern should be randomly changed to a different pattern.

Screenshots or screencast

Kapture.2022-11-09.at.11.12.26.mp4

@kevin940726 kevin940726 added the [Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced label Nov 9, 2022
@codesandbox
Copy link

codesandbox bot commented Nov 9, 2022

CodeSandbox logoCodeSandbox logo  Open in CodeSandbox Web Editor | VS Code | VS Code Insiders

@github-actions
Copy link

github-actions bot commented Nov 9, 2022

Size Change: +8.86 kB (+1%)

Total Size: 1.3 MB

Filename Size Change
build/block-editor/index.min.js 176 kB +2.02 kB (+1%)
build/block-editor/style-rtl.css 15.9 kB +137 B (+1%)
build/block-editor/style.css 15.9 kB +128 B (+1%)
build/block-library/blocks/group/editor-rtl.css 654 B +260 B (+66%) 🆘
build/block-library/blocks/group/editor.css 654 B +260 B (+66%) 🆘
build/block-library/blocks/navigation/editor-rtl.css 2.15 kB +52 B (+2%)
build/block-library/blocks/navigation/editor.css 2.16 kB +52 B (+2%)
build/block-library/blocks/navigation/style-rtl.css 2.21 kB +19 B (+1%)
build/block-library/blocks/navigation/style.css 2.2 kB +21 B (+1%)
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB +27 B (+1%)
build/block-library/blocks/query-pagination/style-rtl.css 288 B +6 B (+2%)
build/block-library/blocks/query-pagination/style.css 284 B +6 B (+2%)
build/block-library/blocks/query/editor-rtl.css 440 B +1 B (0%)
build/block-library/blocks/query/editor.css 440 B +1 B (0%)
build/block-library/blocks/table/theme-rtl.css 172 B -3 B (-2%)
build/block-library/blocks/table/theme.css 172 B -3 B (-2%)
build/block-library/editor-rtl.css 11.5 kB +180 B (+2%)
build/block-library/editor.css 11.4 kB +173 B (+2%)
build/block-library/index.min.js 194 kB +1.26 kB (+1%)
build/block-library/style-rtl.css 12.4 kB +25 B (0%)
build/block-library/style.css 12.4 kB +22 B (0%)
build/block-library/theme-rtl.css 704 B -9 B (-1%)
build/block-library/theme.css 708 B -8 B (-1%)
build/components/index.min.js 203 kB -80 B (0%)
build/components/style-rtl.css 11.5 kB +220 B (+2%)
build/components/style.css 11.5 kB +220 B (+2%)
build/edit-navigation/index.min.js 16.2 kB +59 B (0%)
build/edit-navigation/style-rtl.css 4.06 kB +64 B (+2%)
build/edit-navigation/style.css 4.06 kB +66 B (+2%)
build/edit-post/index.min.js 34.4 kB +311 B (+1%)
build/edit-post/style-rtl.css 7.39 kB +66 B (+1%)
build/edit-post/style.css 7.38 kB +62 B (+1%)
build/edit-site/index.min.js 61 kB +2.87 kB (+5%) 🔍
build/edit-site/style-rtl.css 8.4 kB +35 B (0%)
build/edit-site/style.css 8.39 kB +36 B (0%)
build/edit-widgets/index.min.js 16.7 kB +57 B (0%)
build/edit-widgets/style-rtl.css 4.41 kB +68 B (+2%)
build/edit-widgets/style.css 4.41 kB +69 B (+2%)
build/editor/index.min.js 43.7 kB +49 B (0%)
build/keycodes/index.min.js 1.83 kB +2 B (0%)
build/rich-text/index.min.js 10.7 kB +49 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/index.min.js 7.09 kB
build/block-directory/style-rtl.css 990 B
build/block-directory/style.css 991 B
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 126 B
build/block-library/blocks/audio/theme.css 126 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 84 B
build/block-library/blocks/avatar/style.css 84 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 482 B
build/block-library/blocks/button/editor.css 482 B
build/block-library/blocks/button/style-rtl.css 532 B
build/block-library/blocks/button/style.css 532 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.55 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 126 B
build/block-library/blocks/embed/theme.css 126 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 346 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 948 B
build/block-library/blocks/gallery/editor.css 950 B
build/block-library/blocks/gallery/style-rtl.css 1.53 kB
build/block-library/blocks/gallery/style.css 1.53 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 327 B
build/block-library/blocks/html/editor.css 329 B
build/block-library/blocks/image/editor-rtl.css 880 B
build/block-library/blocks/image/editor.css 880 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 B
build/block-library/blocks/latest-comments/style-rtl.css 298 B
build/block-library/blocks/latest-comments/style.css 298 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 712 B
build/block-library/blocks/navigation-link/editor.css 711 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/view.min.js 443 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 363 B
build/block-library/blocks/page-list/editor.css 363 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 315 B
build/block-library/blocks/post-featured-image/style.css 315 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 464 B
build/block-library/blocks/shortcode/editor.css 464 B
build/block-library/blocks/site-logo/editor-rtl.css 490 B
build/block-library/blocks/site-logo/editor.css 490 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 322 B
build/block-library/blocks/spacer/editor.css 322 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 505 B
build/block-library/blocks/table/editor.css 505 B
build/block-library/blocks/table/style-rtl.css 631 B
build/block-library/blocks/table/style.css 631 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 235 B
build/block-library/blocks/template-part/editor.css 235 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 691 B
build/block-library/blocks/video/editor.css 694 B
build/block-library/blocks/video/style-rtl.css 174 B
build/block-library/blocks/video/style.css 174 B
build/block-library/blocks/video/theme-rtl.css 126 B
build/block-library/blocks/video/theme.css 126 B
build/block-library/classic-rtl.css 162 B
build/block-library/classic.css 162 B
build/block-library/common-rtl.css 1.02 kB
build/block-library/common.css 1.02 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 49.9 kB
build/compose/index.min.js 12.2 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 kB
build/data-controls/index.min.js 653 B
build/data/index.min.js 8.08 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.7 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/editor/style-rtl.css 3.6 kB
build/editor/style.css 3.59 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/experiments/index.min.js 868 B
build/format-library/index.min.js 6.95 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.77 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/list-reusable-blocks/index.min.js 2.13 kB
build/list-reusable-blocks/style-rtl.css 835 B
build/list-reusable-blocks/style.css 835 B
build/media-utils/index.min.js 2.93 kB
build/notices/index.min.js 963 B
build/nux/index.min.js 2.06 kB
build/nux/style-rtl.css 732 B
build/nux/style.css 728 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.22 kB
build/preferences/index.min.js 1.33 kB
build/primitives/index.min.js 944 B
build/priority-queue/index.min.js 1.58 kB
build/react-i18n/index.min.js 696 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.74 kB
build/reusable-blocks/index.min.js 2.21 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/server-side-render/index.min.js 1.77 kB
build/shortcode/index.min.js 1.53 kB
build/style-engine/index.min.js 1.48 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.61 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.08 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.21 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.19 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@jameskoster
Copy link
Contributor

jameskoster commented Nov 9, 2022

Exciting!

The Shuffle button is appearing, but I am seeing results that I would consider to be unexpected. For example I have a Group containing a single Paragraph block, and when I shuffle I'm presented with Header and Footer patterns.

For the purpose of shuffle matches, I suppose we should consider things like Site Title, Site Logo, Site Tagline, Navigation, etc to be 'content'. Or perhaps there is a better way?

@kevin940726
Copy link
Member Author

but I am seeing results that I would consider to be unexpected. For example I have a Group containing a single Paragraph block, and when I shuffle I'm presented with Header and Footer patterns.

Yep! That's a known side effect that could happen as discussed in #44581.

I suppose we should consider things like Site Title, Site Logo, Site Tagline, Navigation, etc to be 'content'. Or perhaps there is a better way?

This handcrafted list could properly work for core blocks but not for third-party blocks. I'm not sure if there's a better way though, at least not without introducing a new API. 🤔

@jameskoster
Copy link
Contributor

I can't speak to the technical side, but for this feature to work it seems very important that the 'content' blocks remain consistent as you shuffle. Would it involve a new API to allow blocks to specify whether they are 'content' blocks?

@kevin940726
Copy link
Member Author

There's already an API (__experimentalRole) to specify which attribute has the content role, which is what I'm using in this PR too. Right now, I identify blocks that have any content attribute as content blocks. So for instance, a Paragraph block is a content block because it has the content attribute which has __experimentalRole: "content".

Upon shuffling, All the blocks and their attributes are changed except for the content attributes. That is, any attribute in the Paragraph block gets shuffled into what is defined in the pattern, except for the content attribute. This allows us to keep the user input (which is the only thing user can edit in contentOnly mode) when shuffling.

Is this the expected result you have in mind?

@jameskoster
Copy link
Contributor

Is this the expected result you have in mind?

Yeah how you described it sounds fine. So it seems we need to add __experimentalRole: "content" to the relevant attributes in blocks like Site Title, Site Tagline, Site Logo. That would 'fix' the 'issue' I described in #45618 (comment).

@annezazu annezazu mentioned this pull request Nov 15, 2022
57 tasks
@talldan
Copy link
Contributor

talldan commented Nov 17, 2022

So it seems we need to add __experimentalRole: "content" to the relevant attributes in blocks like Site Title, Site Tagline, Site Logo

Interesting. The technical problem is that those blocks don't have attributes that can be marked with the content role. The content for those blocks is stored as part of the site itself.

This is at the very least a good discovery to make, even if it is a bit of a problem.

@youknowriad
Copy link
Contributor

Yeah hard problem here, here are some ideas:

Flatten all blocks and inner blocks in the patterns.

This sounded weird to me, while there are some blocks that need to be ignored while comparing (mostly style related blocks like "groups", "cover"....), some container blocks shouldn't be ignored like "quote", "list" blocks and I believe the new versions of these blocks don't have a "content" role either.

The technical problem is that those blocks don't have attributes that can be marked with the content role. The content for those blocks is stored as part of the site itself.

This is also an interesting observation that may get us close to what should be the algorithm here :)


So maybe the algorithm should be something like:

1- Take the list of blocks and remove from the tree all container blocks that are just about layout: groups, covers, columns, spacer (not sure if there are others)
2- Compare the remaining trees and the list of remaining blocks should match. The position of the blocks might differ but all the blocks should be available in the new pattern.
3- Swap the pattern while retaining the "content" attributes (if they exist) in the matching blocks.

The problem I see in my algorithm is that if a pattern has "three" paragraphs, we would be able to shuffle it into a "four" paragraph pattern but we won't be able to get back to "three" anymore. So we could consider only matching exact number of filtered blocks. The problem is that we might end up with too few options.

Also another problem is that if you can't transform from a query with "post-title" and "post-content" to a query with just "post-content". Makes me wonder if some blocks should be considered mandatory and others optional for example:

  • A query block is mandatory
  • All post blocks are optional
  • A quote block is mandatory
  • A button block (probably mandatory)
  • A paragraph block (probably mandatory / arguable)
  • A list block (I can't really tell)

Anyway, this is just some rumbling to try to get us into the right direction. No perfect solution here it seems.

@youknowriad
Copy link
Contributor

The other thing that comes to my mind is that it seems that this is an AI ML problem. Maybe we can train a model manually using the pattern directory and apply it here. I'm not expert in ML but conceptually it seems like a good fit. cc @ellatrix

@talldan
Copy link
Contributor

talldan commented Nov 18, 2022

The problem is that we might end up with too few options.

Yeah, I think this is a problem 🤔 The more accurate the system is, the fewer matches that can be presented, and actually that might make it less useful and less serendipitous.

It could be possible to loosen the rules and instead switch to a model where content loss is ok, but I think the UI would have to be different to a shuffle, and offer an easy way back to the original set of blocks (this might be a valid feature to provide anyway).

@jameskoster
Copy link
Contributor

The problem is that we might end up with too few options

I agree it would be a shame if there was only 2 patterns to shuffle between, but imo it's not a deal-breaker. I'd say that experience is significantly better when compared to shuffling between incompatible pattern configs.

If we're worried about underwhelming, we might say "only allow shuffling when there are >x matches".

It's also worth noting that it's a problem that will diminish over time after we connect to the pattern directory, and the directory itself grows.

@kevin940726
Copy link
Member Author

In b35142a, I inline two functions filterBlocksForShuffle and compareFilteredBlocks for implementing the algorithm. The names are intentionally vague until we decide the path we want to take.

This commit roughly follows the algo @youknowriad shared in #45618 (comment). Instead of hardcoding the layout blocks, I use the category field to filter out those in the design category. This is not ideal either though, since it also won't work with third-party blocks. I wonder if there's something like __experimentalRole: "layout" for blockTypes?

This approach is obviously very precise though. Let's test it out and see if we can spot something we can improve.

@talldan
Copy link
Contributor

talldan commented Nov 22, 2022

I wonder if there's something like __experimentalRole: "layout" for blockTypes?

@kevin940726 Possibly hasBlockSupport( blockName, '__experimentalLayout' )?

@kevin940726
Copy link
Member Author

That could work! That will also match something like navigation and post-content, but it might be acceptable. Used it in 30845c6.

@talldan
Copy link
Contributor

talldan commented Nov 22, 2022

It does feel like checking block supports is a better option, but at the same time I'd imagine the navigation block shouldn't be excluded (potentially its ref (selected menu) should carry over between patterns?). I'm also not sure how the nav block is intended to work in contentOnly mode. I guess it would be uneditable. It's in a difficult gray area as a block.

@talldan
Copy link
Contributor

talldan commented Dec 5, 2022

Gave this a test. It works very well with some patterns. I tried inserting a basic footer (Default footer from TT3), and it shuffled between a few different options:

Kapture.2022-12-05.at.15.48.02.mp4

As you can see, it doesn't consider the navigation block as content so it will use patterns that don't include it and may lose the selected menu.

The other thing I noticed is that I inserted this pattern (Two columns of text and title):
Screen Shot 2022-12-05 at 3 50 41 pm

It doesn't come wrapped in a group block by default, so I wrapped it myself and added the content locking attribute. When I clicked shuffle, I guess the only available pattern was the one I inserted and it removed the wrapping group block. It feels like the contentOnly wrapper should be preserved whenever shuffling, otherwise the 'Shuffle' button can unexpectedly disappear.

@kevin940726
Copy link
Member Author

It feels like the contentOnly wrapper should be preserved whenever shuffling, otherwise the 'Shuffle' button can unexpectedly disappear.

It is preserved, but only at the top level. As soon as we modify the pattern manually (wrap it with a group block in this case), we can no longer reference it back to the original pattern (performed by a naive algorithm in areBlocksAlike), hence we include the original pattern in the shuffle list. If the contentOnly attribute only applies to the group block then I suppose we can do something as you mentioned automatically? 🤔

@mtias
Copy link
Member

mtias commented Dec 5, 2022

Here's my take on this:

  • For template part / semantic patterns we should not restrict things (all headers, footer, query blocks should be available for cycling) — the semantic role assumes the pairing and discarded blocks here are easy to retrieve so they don't need mapping (i.e. a site title would always be available).
  • For arbitrary pattern sections we should be restrictive within a given category (i.e. cycle through "call to action" patterns, through "gallery" patterns, etc) while mapping content attributes and apply our logic on top of it.
    • We should try to hold on to discarded data until a block is unselected, so if you cycle through a loop you can get back to your possibly missed or discarded blocks.

Ultimately, I agree we should not develop too many custom heuristics and that pattern matching is something we could employ AI training to assist with.

@kevin940726
Copy link
Member Author

kevin940726 commented Dec 7, 2022

@mtias Thanks for the feedback! Not sure if I understand it correctly, but there are some technical difficulties preventing us from implementing some of the details you mentioned.

  1. There is currently no way to determine a pattern's semantic role after being inserted. We can't distinguish if it's a header, footer, text, or a combination of either.
  2. There is also currently no API to determine if a block or an attribute is essential to the pattern. For instance, a site title might be essential to the pattern, and we want to keep it when cycling through different options.
  3. After shuffling to a different pattern, the original information is lost. The whole blocks get replaced and the state is reset. This technically is possible though, we can store the state elsewhere semi-globally (possibly Redux store). We do want to make sure what the expection is though as this can get tricky with non-idiomatic code.

Ultimately, I agree we should not develop too many custom heuristics and that pattern matching is something we could employ AI training to assist with.

Are we saying that maybe it's worth holding this for now until we research the AI possibilities? How do you imagine the implementation with AI would be? Do we implement the AI in the browser or in the users' WordPress instance? Or do we implement it in a WordPress.org API and call it from the client side?

@kevin940726
Copy link
Member Author

I opened an alternative PR in #47594 with a slightly different approach: instead of shuffling on inserted patterns, we only allow shuffling on the pattern blocks. This way, we can keep the information of the pattern and shuffle to different patterns with the same categories.

@kevin940726 kevin940726 deleted the add/shuffle-patterns branch June 26, 2023 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants