From 5d25b6e5120b8145613e42df93e711d006aecf4e Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Fri, 4 Oct 2024 15:19:30 +0700 Subject: [PATCH] Removed _ObsoleteListIndex.tsx This file is no longer used --- .../src/components/_ObsoleteListIndex.tsx | 538 ------------------ 1 file changed, 538 deletions(-) delete mode 100644 apps/admin-x-activitypub/src/components/_ObsoleteListIndex.tsx diff --git a/apps/admin-x-activitypub/src/components/_ObsoleteListIndex.tsx b/apps/admin-x-activitypub/src/components/_ObsoleteListIndex.tsx deleted file mode 100644 index 021cbbf1b6..0000000000 --- a/apps/admin-x-activitypub/src/components/_ObsoleteListIndex.tsx +++ /dev/null @@ -1,538 +0,0 @@ -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'; -import {Avatar, Button, ButtonGroup, Heading, Icon, List, ListItem, Page, SelectOption, SettingValue, ViewContainer, ViewTab} from '@tryghost/admin-x-design-system'; -import {useBrowseSite} from '@tryghost/admin-x-framework/api/site'; -import {useQuery} from '@tanstack/react-query'; -import {useRouting} from '@tryghost/admin-x-framework/routing'; - -interface ViewArticleProps { - object: ObjectProperties, - onBackToList: () => void; -} - -type Activity = { - type: string, - object: { - type: string - } -} - -export function useBrowseInboxForUser(handle: string) { - const site = useBrowseSite(); - const siteData = site.data?.site; - const siteUrl = siteData?.url ?? window.location.origin; - const api = new ActivityPubAPI( - new URL(siteUrl), - new URL('/ghost/api/admin/identities/', window.location.origin), - handle - ); - return useQuery({ - queryKey: [`inbox:${handle}`], - async queryFn() { - return api.getInbox(); - } - }); -} - -function useFollowersCountForUser(handle: string) { - const site = useBrowseSite(); - const siteData = site.data?.site; - const siteUrl = siteData?.url ?? window.location.origin; - const api = new ActivityPubAPI( - new URL(siteUrl), - new URL('/ghost/api/admin/identities/', window.location.origin), - handle - ); - return useQuery({ - queryKey: [`followersCount:${handle}`], - async queryFn() { - return api.getFollowersCount(); - } - }); -} - -function useFollowingCountForUser(handle: string) { - const site = useBrowseSite(); - const siteData = site.data?.site; - const siteUrl = siteData?.url ?? window.location.origin; - const api = new ActivityPubAPI( - new URL(siteUrl), - new URL('/ghost/api/admin/identities/', window.location.origin), - handle - ); - return useQuery({ - queryKey: [`followingCount:${handle}`], - async queryFn() { - return api.getFollowingCount(); - } - }); -} - -const ActivityPubComponent: React.FC = () => { - const {updateRoute} = useRouting(); - - // TODO: Replace with actual user ID - const {data: activities = []} = useBrowseInboxForUser('index'); - const {data: followersCount = 0} = useFollowersCountForUser('index'); - const {data: followingCount = 0} = useFollowingCountForUser('index'); - - const [articleContent, setArticleContent] = useState(null); - const [, setArticleActor] = useState(null); - - const handleViewContent = (object: ObjectProperties, actor: ActorProperties) => { - setArticleContent(object); - setArticleActor(actor); - }; - - const handleBackToList = () => { - setArticleContent(null); - }; - - const [selectedOption, setSelectedOption] = useState({label: 'Feed', value: 'feed'}); - - const [selectedTab, setSelectedTab] = useState('inbox'); - - const inboxTabActivities = activities.filter((activity: Activity) => { - const isCreate = activity.type === 'Create' && ['Article', 'Note'].includes(activity.object.type); - const isAnnounce = activity.type === 'Announce' && activity.object.type === 'Note'; - - return isCreate || isAnnounce; - }); - const activityTabActivities = activities.filter((activity: Activity) => activity.type === 'Create' && activity.object.type === 'Article'); - const likeTabActivies = activities.filter((activity: Activity) => activity.type === 'Like'); - - const tabs: ViewTab[] = [ - { - id: 'inbox', - title: 'Inbox', - contents: ( -
- {inboxTabActivities.length > 0 ? ( -
    - {inboxTabActivities.reverse().map(activity => ( -
  • handleViewContent(activity.object, activity.actor)} - > - -
  • - ))} -
- ) : ( -
-
- Ghost site logos - - Welcome to ActivityPub - -

- We’re so glad to have you on board! At the moment, you can follow other Ghost sites and enjoy their content right here inside Ghost. -

-

- You can see all of the users on the right—find your favorite ones and give them a follow. -

-
-
- )} -
- ) - }, - { - id: 'activity', - title: 'Activity', - contents: ( -
-
    - {activityTabActivities.reverse().map(activity => ( -
  • handleViewContent(activity.object, activity.actor)} - > - -
  • - ))} -
-
- ) - }, - { - id: 'likes', - title: 'Likes', - contents: ( -
- - {likeTabActivies.reverse().map(activity => ( - } - id='list-item' - title={ -
- {activity.actor.name} - liked your post - {activity.object.name} -
- } - /> - ))} -
-
- ) - }, - { - id: 'profile', - title: 'Profile', - contents: ( -
-
-
-
-
updateRoute('/view-following')}> - {followingCount} - Following -
-
updateRoute('/view-followers')}> - {followersCount} - Followers -
-
-
-
- ) - } - ]; - - return ( - <> - - {!articleContent ? ( - { - setSelectedOption({label: 'Feed', value: 'feed'}); - } - - }, - { - icon: 'cardview', - size: 'sm', - iconColorClass: selectedOption.value === 'inbox' ? 'text-black' : 'text-grey-500', - onClick: () => { - setSelectedOption({label: 'Inbox', value: 'inbox'}); - } - } - ]} clearBg={true} link outlineOnMobile />]} - firstOnPage={true} - primaryAction={{ - title: 'Follow', - onClick: () => { - updateRoute('follow-site'); - }, - icon: 'add' - }} - selectedTab={selectedTab} - stickyHeader={true} - tabs={tabs} - title='ActivityPub' - toolbarBorder={true} - type='page' - onTabChange={setSelectedTab} - > - - - ) : ( - - )} - - - - ); -}; - -const ArticleBody: React.FC<{heading: string, image: string|undefined, html: string}> = ({heading, image, html}) => { - const site = useBrowseSite(); - const siteData = site.data?.site; - - const iframeRef = useRef(null); - - const cssContent = articleBodyStyles(siteData?.url.replace(/\/$/, '')); - - const htmlContent = ` - - - ${cssContent} - - -
-

${heading}

-${image && - `
- ${heading} -
` -} -
-
- ${html} -
- - -`; - - useEffect(() => { - const iframe = iframeRef.current; - if (iframe) { - iframe.srcdoc = htmlContent; - } - }, [htmlContent]); - - return ( -
- -
- ); -}; - -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'); - - const plainTextContent = doc.body.textContent; - let previewContent = ''; - if (object.preview) { - const previewDoc = parser.parseFromString(object.preview.content || '', 'text/html'); - previewContent = previewDoc.body.textContent || ''; - } else if (object.type === 'Note') { - previewContent = plainTextContent || ''; - } - - 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); - - const handleLikeClick = (event: React.MouseEvent | undefined) => { - event?.stopPropagation(); - setIsClicked(true); - setIsLiked(!isLiked); - setTimeout(() => setIsClicked(false), 300); // Reset the animation class after 300ms - }; - - let author = actor; - if (type === 'Announce' && object.type === 'Note') { - author = typeof object.attributedTo === 'object' ? object.attributedTo as ActorProperties : actor; - } - - if (layout === 'feed') { - return ( - <> - {object && ( -
- {(type === 'Announce' && object.type === 'Note') &&
-
- {actor.name} reposted -
} -
- -
-
-
- {author.name} - {getRelativeTimestamp(date)} -
-
- {getUsername(author)} -
-
-
-
- {object.name && {object.name}} -
- {/*

{object.content}

*/} - {renderAttachment(object)} -
-
-
-
-
-
-
-
- )} - - ); - } else if (layout === 'inbox') { - return ( - <> - {object && ( -
-
- - {actor.name} - {/* {getUsername(actor)} */} - {timestamp} -
-
-
-
- {object.name} -
-

{previewContent}

-
-
-
- {/* {image &&
- -
} */} -
-
- {/*
*/} -
- )} - - ); - } -}; - -const ViewArticle: React.FC = ({object, onBackToList}) => { - const {updateRoute} = useRouting(); - - const [isClicked, setIsClicked] = useState(false); - const [isLiked, setIsLiked] = useState(false); - - const handleLikeClick = (event: React.MouseEvent | undefined) => { - event?.stopPropagation(); - setIsClicked(true); - setIsLiked(!isLiked); - setTimeout(() => setIsClicked(false), 300); // Reset the animation class after 300ms - }; - - return ( - - -
-
-
-
-
-
-
-
-
-
-
- {object.type === 'Note' && ( -
- {object.content &&
} - {renderAttachment(object)} -
)} - {object.type === 'Article' && } -
-
-
- ); -}; - -export default ActivityPubComponent;