From 3a830e214ecbfb2fee3d4370a5bf838b6f258c0f Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Mon, 15 Apr 2024 08:42:33 +0300 Subject: [PATCH] Editor: Add wordcount and reading time info in post card (#60672) Co-authored-by: ntsekouras Co-authored-by: mcsf Co-authored-by: swissspidy Co-authored-by: jameskoster Co-authored-by: tobifjellner Co-authored-by: NekoJonez --- .../src/components/post-actions/index.js | 2 +- .../src/components/post-card-panel/index.js | 122 +++++++++++++----- 2 files changed, 93 insertions(+), 31 deletions(-) diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index b3a6cee47d31f2..379231b0a9dff0 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -89,7 +89,7 @@ export default function PostActions( { onActionPerformed } ) { { - const { - getEditedPostAttribute, - getCurrentPostType, - getCurrentPostId, - __experimentalGetTemplateInfo, - } = select( editorStore ); - const { getEditedEntityRecord } = select( coreStore ); - const _type = getCurrentPostType(); - const _id = getCurrentPostId(); - const _record = getEditedEntityRecord( 'postType', _type, _id ); - const _templateInfo = __experimentalGetTemplateInfo( _record ); - return { - title: - _templateInfo?.title || getEditedPostAttribute( 'title' ), - modified: getEditedPostAttribute( 'modified' ), - id: _id, - postType: _type, - templateInfo: _templateInfo, - icon: unlock( select( editorStore ) ).getPostIcon( _type, { - area: _record?.area, - } ), - }; - } - ); + const { + modified, + title, + templateInfo, + icon, + postType, + postContent, + isPostsPage, + } = useSelect( ( select ) => { + const { + getEditedPostAttribute, + getCurrentPostType, + getCurrentPostId, + __experimentalGetTemplateInfo, + } = select( editorStore ); + const { getEditedEntityRecord, getEntityRecord } = select( coreStore ); + const siteSettings = getEntityRecord( 'root', 'site' ); + const _type = getCurrentPostType(); + const _id = getCurrentPostId(); + const _record = getEditedEntityRecord( 'postType', _type, _id ); + const _templateInfo = __experimentalGetTemplateInfo( _record ); + return { + title: _templateInfo?.title || getEditedPostAttribute( 'title' ), + modified: getEditedPostAttribute( 'modified' ), + id: _id, + postType: _type, + templateInfo: _templateInfo, + icon: unlock( select( editorStore ) ).getPostIcon( _type, { + area: _record?.area, + } ), + isPostsPage: +_id === siteSettings?.page_for_posts, + postContent: getEditedPostAttribute( 'content' ), + }; + }, [] ); const description = templateInfo?.description; const lastEditedText = modified && @@ -62,7 +74,9 @@ export default function PostCardPanel( { className, actions } ) { __( 'Last edited %s.' ), humanTimeDiff( modified ) ); - + const showPostContentInfo = + ! isPostsPage && + ! [ TEMPLATE_POST_TYPE, TEMPLATE_PART_POST_TYPE ].includes( postType ); return (
- { ( description || lastEditedText ) && ( + { ( description || + lastEditedText || + showPostContentInfo ) && ( { description && { description } } + { showPostContentInfo && ( + + ) } { lastEditedText && ( { lastEditedText } ) } @@ -106,3 +125,46 @@ export default function PostCardPanel( { className, actions } ) { ); } + +// Taken from packages/editor/src/components/time-to-read/index.js. +const AVERAGE_READING_RATE = 189; + +// This component renders the wordcount and reading time for the post. +function PostContentInfo( { postContent } ) { + /* + * translators: If your word count is based on single characters (e.g. East Asian characters), + * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. + * Do not translate into your own language. + */ + const wordCountType = _x( 'words', 'Word count type. Do not translate!' ); + const wordsCounted = postContent + ? wordCount( postContent, wordCountType ) + : 0; + if ( ! wordsCounted ) { + return null; + } + const readingTime = Math.round( wordsCounted / AVERAGE_READING_RATE ); + const wordsCountText = sprintf( + // translators: %s: the number of words in the post. + _n( '%s word', '%s words', wordsCounted ), + wordsCounted.toLocaleString() + ); + const minutesText = + readingTime <= 1 + ? __( '1 minute' ) + : sprintf( + // translators: %s: the number of minutes to read the post. + _n( '%s minute', '%s minutes', readingTime ), + readingTime.toLocaleString() + ); + return ( + + { sprintf( + /* translators: 1: How many words a post has. 2: the number of minutes to read the post (e.g. 130 words, 2 minutes read time.) */ + __( '%1$s, %2$s read time.' ), + wordsCountText, + minutesText + ) } + + ); +}