From 9d0d1d5c69f8852d908ef578c2597c67b3d237cc Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Tue, 1 Oct 2024 16:24:34 +0700 Subject: [PATCH] Improve selection of image or link to use as cover --- src/components/posts/view-post/PostPage.tsx | 30 ++++++-------- src/components/posts/view-post/helpers.tsx | 44 ++++++++++++++++++--- src/graphql/apis/mappers.ts | 3 +- src/graphql/apis/types.ts | 2 +- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/components/posts/view-post/PostPage.tsx b/src/components/posts/view-post/PostPage.tsx index 72211d69d..0c7081387 100644 --- a/src/components/posts/view-post/PostPage.tsx +++ b/src/components/posts/view-post/PostPage.tsx @@ -44,11 +44,12 @@ import { DfImage } from '../../utils/DfImage' import { DfMd } from '../../utils/DfMd' import Section from '../../utils/Section' import ViewTags from '../../utils/ViewTags' -import Embed, { getEmbedLinkType, getGleevVideoId, getYoutubeVideoId } from '../embed/Embed' +import Embed from '../embed/Embed' import { StatsPanel } from '../PostStats' import { usePostViewTracker } from '../PostViewSubmitter' import ViewPostLink from '../ViewPostLink' import { + getCoverImageOrEmbed, HiddenPostAlert, OriginalPostPanel, PostActionsPanel, @@ -147,15 +148,7 @@ const InnerPostPage: NextPage = props => { } } - let usedImage = image - if (!usedImage && link) { - const embedType = getEmbedLinkType(link) - if (embedType === 'Youtube') { - usedImage = `https://i3.ytimg.com/vi/${getYoutubeVideoId(link)}/maxresdefault.jpg` - } else if (embedType === 'Gleev (Joystream)') { - usedImage = `https://assets.joyutils.org/video/${getGleevVideoId(link)}/thumbnail` - } - } + const { coverLink, imageAsMeta, type } = getCoverImageOrEmbed(content) const isSpaceAlreadyRenderedInSidebar = isNotMobile @@ -165,7 +158,7 @@ const InnerPostPage: NextPage = props => { title: metaTitle || defaultMetaTitle, forceTitle, desc: content.summary, - image: usedImage, + image: imageAsMeta, tags, canonical: postUrl(spaceStruct, postData.post), externalCanonical: content.canonical, @@ -212,13 +205,14 @@ const InnerPostPage: NextPage = props => { {titleMsg} )} - {image ? ( -
- -
- ) : ( - link && - )} + {coverLink && + (type === 'image' ? ( +
+ +
+ ) : ( + + ))} {body && } diff --git a/src/components/posts/view-post/helpers.tsx b/src/components/posts/view-post/helpers.tsx index 80bda170b..85e6cdb46 100644 --- a/src/components/posts/view-post/helpers.tsx +++ b/src/components/posts/view-post/helpers.tsx @@ -45,7 +45,7 @@ import { SpaceNameAsLink } from '../../spaces/ViewSpace' import { formatDate, isHidden, toShortUrl, useIsVisible } from '../../utils' import { SummarizeMd } from '../../utils/md/SummarizeMd' import ViewTags from '../../utils/ViewTags' -import Embed, { getEmbedLinkType } from '../embed/Embed' +import Embed, { getEmbedLinkType, getGleevVideoId, getYoutubeVideoId } from '../embed/Embed' import { isPinnedPost } from '../pinned-post' import { ShareDropdown } from '../share/ShareDropdown' import ViewPostLink from '../ViewPostLink' @@ -528,21 +528,21 @@ export const InfoPostPreview: FC = props => { post: { struct, content }, } = postDetails - const embedType = getEmbedLinkType(content?.link) - const shouldRenderEmbed = embedType && !content?.image if (!struct || !content) return null + const { coverLink, type } = getCoverImageOrEmbed(content) + return (
- {shouldRenderEmbed && } + {coverLink && type === 'embed' && } {withTags && } {/* {withStats && } */} @@ -632,3 +632,37 @@ export function PinnedPostIcon({ postId }: { postId: string }) {
) } + +export function getCoverImageOrEmbed(content: PostContentType) { + const { image, link } = content + + let imageAsCover = '' + // first priority, if image is put directly by user, not from body + // added data from squid mapper + if (!(content as unknown as { isImageFromBody: boolean }).isImageFromBody && image) { + imageAsCover = image + } + // second priority, to get the cover image from supported link + const embedType = getEmbedLinkType(link) + if (!imageAsCover && link) { + if (embedType === 'Youtube') { + imageAsCover = `https://i3.ytimg.com/vi/${getYoutubeVideoId(link)}/maxresdefault.jpg` + } else if (embedType === 'Gleev (Joystream)') { + imageAsCover = `https://assets.joyutils.org/video/${getGleevVideoId(link)}/thumbnail` + } + } + // third priority, if there is no embeddable link, use the first image from body + if (!imageAsCover && !embedType && image) { + imageAsCover = image + } + // if there is an embeddable link, it will use the link as the cover + + const imageAsMeta = imageAsCover || image + + // if there is no image, use link as embed cover + return { + type: (imageAsCover ? 'image' : 'embed') as 'image' | 'embed', + coverLink: imageAsCover || link, + imageAsMeta, + } +} diff --git a/src/graphql/apis/mappers.ts b/src/graphql/apis/mappers.ts index b876753e9..bd0b53c35 100644 --- a/src/graphql/apis/mappers.ts +++ b/src/graphql/apis/mappers.ts @@ -98,12 +98,13 @@ function getFirstImageLink(mdText: string) { return match ? match[1] : null } export const mapSimplePostFragment = (post: PostSimpleFragment): PostSimpleFragmentMapped => { - const getContent = (): PostContent => { + const getContent = (): PostContent & { isImageFromBody: boolean } => { const summary = summarizeMd(post.body ?? '') const firstImageLink = getFirstImageLink(post.body ?? '') return { summary: summary.summary ?? '', image: post.image || firstImageLink || '', + isImageFromBody: !post.image && !!firstImageLink, title: post.title ?? '', link: post.link ?? undefined, body: post.body || '', diff --git a/src/graphql/apis/types.ts b/src/graphql/apis/types.ts index a06483148..e984e09c0 100644 --- a/src/graphql/apis/types.ts +++ b/src/graphql/apis/types.ts @@ -9,7 +9,7 @@ export type SpaceSimpleFragmentMapped = SpaceStruct & { export type PostSimpleFragmentMapped = PostStruct & { originalPostId?: string rootPostId?: string -} & { ipfsContent?: PostContent } +} & { ipfsContent?: PostContent & { isImageFromBody: boolean } } export type ProfileSimpleFragmentMapped = ProfileSpaceIdByAccount // Full Fragment Results