diff --git a/apps/admin-x-activitypub/src/components/ListIndex.tsx b/apps/admin-x-activitypub/src/components/ListIndex.tsx index 9f9d1393ec..62f05786b7 100644 --- a/apps/admin-x-activitypub/src/components/ListIndex.tsx +++ b/apps/admin-x-activitypub/src/components/ListIndex.tsx @@ -1,6 +1,7 @@ import ActivityPubWelcomeImage from '../assets/images/ap-welcome.png'; import React, {useEffect, useRef, useState} from 'react'; import articleBodyStyles from './articleBodyStyles'; +import getRelativeTimestamp from '../utils/get-relative-timestamp'; import getUsername from '../utils/get-username'; import {ActivityPubAPI} from '../api/activitypub'; import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; @@ -204,7 +205,7 @@ const ActivityPubComponent: React.FC = () => { title: 'Profile', contents: (
-
+
updateRoute('/view-following')}> @@ -285,15 +286,15 @@ const ArticleBody: React.FC<{heading: string, image: string|undefined, html: str ${cssContent} -
-

${heading}

+
+

${heading}

${image && - `
- ${heading} + `
+ ${heading}
` }
-
+
${html}
@@ -312,16 +313,72 @@ ${image &&
); }; +function renderAttachment(object: ObjectProperties) { + let attachment; + if (object.image) { + attachment = object.image; + } + + if (object.type === 'Note' && !attachment) { + attachment = object.attachment; + } + + if (!attachment) { + return null; + } + + if (Array.isArray(attachment)) { + const attachmentCount = attachment.length; + + let gridClass = ''; + if (attachmentCount === 1) { + gridClass = 'grid-cols-1'; // Single image, full width + } else if (attachmentCount === 2) { + gridClass = 'grid-cols-2'; // Two images, side by side + } else if (attachmentCount === 3 || attachmentCount === 4) { + gridClass = 'grid-cols-2'; // Three or four images, two per row + } + + return ( +
+ {attachment.map((item, index) => ( + {`attachment-${index}`} + ))} +
+ ); + } + + switch (attachment.mediaType) { + case 'image/jpeg': + case 'image/png': + case 'image/gif': + return attachment; + case 'video/mp4': + case 'video/webm': + return
+
; + + case 'audio/mpeg': + case 'audio/ogg': + return
+
; + default: + return null; + } +} + const ObjectContentDisplay: React.FC<{actor: ActorProperties, object: ObjectProperties, layout: string, type: string }> = ({actor, object, layout, type}) => { const parser = new DOMParser(); const doc = parser.parseFromString(object.content || '', 'text/html'); @@ -335,55 +392,11 @@ const ObjectContentDisplay: React.FC<{actor: ActorProperties, object: ObjectProp previewContent = plainTextContent || ''; } - const renderAttachment = () => { - let attachment; - if (object.image) { - attachment = object.image; - } - - if (object.type === 'Note' && !attachment) { - attachment = object.attachment; - } - - // const attachment = object.attachment; - if (!attachment) { - return null; - } - - if (Array.isArray(attachment)) { - return ( -
- {attachment.map((item, index) => ( - {`attachment-${index}`} - ))} -
- ); - } - - switch (attachment.mediaType) { - case 'image/jpeg': - case 'image/png': - case 'image/gif': - return attachment; - case 'video/mp4': - case 'video/webm': - return
-
; - - case 'audio/mpeg': - case 'audio/ogg': - return
-
; - default: - return null; - } - }; - const timestamp = new Date(object?.published ?? new Date()).toLocaleDateString('default', {year: 'numeric', month: 'short', day: '2-digit'}) + ', ' + new Date(object?.published ?? new Date()).toLocaleTimeString('default', {hour: '2-digit', minute: '2-digit'}); + const date = new Date(object?.published ?? new Date()); + const [isClicked, setIsClicked] = useState(false); const [isLiked, setIsLiked] = useState(false); @@ -404,18 +417,20 @@ const ObjectContentDisplay: React.FC<{actor: ActorProperties, object: ObjectProp <> {object && (
- {(type === 'Announce' && object.type === 'Note') &&
+ {(type === 'Announce' && object.type === 'Note') &&
{actor.name} reposted
} -
+
-
+
- {author.name} +
+ {author.name} + {getRelativeTimestamp(date)} +
{getUsername(author)} - {timestamp}
@@ -423,9 +438,9 @@ const ObjectContentDisplay: React.FC<{actor: ActorProperties, object: ObjectProp {object.name && {object.name}}
{/*

{object.content}

*/} - {renderAttachment()} + {renderAttachment(object)}
-
@@ -455,7 +470,7 @@ const ObjectContentDisplay: React.FC<{actor: ActorProperties, object: ObjectProp

{previewContent}

-
@@ -499,14 +514,19 @@ const ViewArticle: React.FC = ({object, onBackToList}) => {
-
- + {object.type === 'Note' && ( +
+ {object.content &&
} + {renderAttachment(object)} +
)} + {object.type === 'Article' && }