From 3cbc28bdbb129eb7bb367a1842c20ae5eec16ce3 Mon Sep 17 00:00:00 2001 From: Djordje Vlaisavljevic Date: Mon, 28 Oct 2024 14:26:35 +0100 Subject: [PATCH] WIP ref https://linear.app/ghost/issue/AP-540/clicking-comment-icon-on-posts-and-likes-tabs-of-your-profile-doesnt --- .../src/components/Inbox.tsx | 44 +++--------------- .../src/components/Profile.tsx | 46 ++++++++++++++----- .../src/hooks/useArticleModal.ts | 27 +++++++++++ .../src/utils/content-helpers.ts | 25 ++++++++++ 4 files changed, 94 insertions(+), 48 deletions(-) create mode 100644 apps/admin-x-activitypub/src/hooks/useArticleModal.ts create mode 100644 apps/admin-x-activitypub/src/utils/content-helpers.ts diff --git a/apps/admin-x-activitypub/src/components/Inbox.tsx b/apps/admin-x-activitypub/src/components/Inbox.tsx index 3a359e6075..d37b57cbbc 100644 --- a/apps/admin-x-activitypub/src/components/Inbox.tsx +++ b/apps/admin-x-activitypub/src/components/Inbox.tsx @@ -1,24 +1,23 @@ import APAvatar from './global/APAvatar'; -import ActivityItem, {type Activity} from './activities/ActivityItem'; +import ActivityItem from './activities/ActivityItem'; import ActivityPubWelcomeImage from '../assets/images/ap-welcome.png'; -import ArticleModal from './feed/ArticleModal'; import FeedItem from './feed/FeedItem'; import MainNavigation from './navigation/MainNavigation'; import NiceModal from '@ebay/nice-modal-react'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useEffect, useRef} from 'react'; import ViewProfileModal from './global/ViewProfileModal'; import getUsername from '../utils/get-username'; -import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; import {Button, Heading, LoadingIndicator} from '@tryghost/admin-x-design-system'; +import {getContentAuthor} from '../utils/content-helpers'; import {useActivitiesForUser, useSuggestedProfiles} from '../hooks/useActivityPubQueries'; +import {useArticleModal} from '../hooks/useArticleModal'; import {useLayout} from '../hooks/layout'; import {useRouting} from '@tryghost/admin-x-framework/routing'; interface InboxProps {} const Inbox: React.FC = ({}) => { - const [, setArticleContent] = useState(null); - const [, setArticleActor] = useState(null); + const {handleViewContent} = useArticleModal(); const {layout} = useLayout(); const { @@ -45,36 +44,6 @@ const Inbox: React.FC = ({}) => { return !activity.object.inReplyTo; }); - const handleViewContent = (object: ObjectProperties, actor: ActorProperties, comments: Activity[], focusReply = false) => { - setArticleContent(object); - setArticleActor(actor); - NiceModal.show(ArticleModal, {object, actor, comments, focusReply}); - }; - - function getContentAuthor(activity: Activity) { - const actor = activity.actor; - const attributedTo = activity.object.attributedTo; - - if (!attributedTo) { - return actor; - } - - if (typeof attributedTo === 'string') { - return actor; - } - - if (Array.isArray(attributedTo)) { - const found = attributedTo.find(item => typeof item !== 'string'); - if (found) { - return found; - } else { - return actor; - } - } - - return attributedTo; - } - // Intersection observer to fetch more activities when the user scrolls // to the bottom of the page const observerRef = useRef(null); @@ -123,7 +92,8 @@ const Inbox: React.FC = ({}) => { onClick={() => handleViewContent( activity.object, getContentAuthor(activity), - activity.object.replies + activity.object.replies, + false )} > = ({}) => { }); }; - const handlePostClick = (activity: Activity) => { - NiceModal.show(ArticleModal, { - object: activity.object, - actor: activity.actor, - comments: activity.object.replies || [] - }); + const {handleViewContent} = useArticleModal(); + + const handlePostClick = (activity: Activity, focusReply: boolean) => { + const object = activity.object; + let author: ActorProperties; + + // Handle different possible formats of attributedTo + if (object?.attributedTo) { + if (Array.isArray(object.attributedTo)) { + // If it's an array, find the first non-string item + const foundAuthor = object.attributedTo.find(item => typeof item !== 'string'); + author = foundAuthor as ActorProperties || activity.actor; + } else if (typeof object.attributedTo === 'string') { + // If it's a string, use the activity actor + author = activity.actor; + } else { + // If it's an object, use it directly + author = object.attributedTo as ActorProperties; + } + } else { + // Fallback to activity actor if no attributedTo + author = activity.actor; + } + + handleViewContent( + object, + author, + object.replies || [], + focusReply + ); }; const tabs = [ @@ -97,14 +121,14 @@ const Profile: React.FC = ({}) => {
  • handlePostClick(activity)} + onClick={() => handlePostClick(activity, false)} > {}} + onCommentClick={() => handlePostClick(activity, true)} /> {index < posts.length - 1 && (
    @@ -142,14 +166,14 @@ const Profile: React.FC = ({}) => {
  • handlePostClick(activity)} + onClick={() => handlePostClick(activity, false)} > {}} + onCommentClick={() => handlePostClick(activity, true)} /> {index < liked.length - 1 && (
    diff --git a/apps/admin-x-activitypub/src/hooks/useArticleModal.ts b/apps/admin-x-activitypub/src/hooks/useArticleModal.ts new file mode 100644 index 0000000000..d898f8fc91 --- /dev/null +++ b/apps/admin-x-activitypub/src/hooks/useArticleModal.ts @@ -0,0 +1,27 @@ +import ArticleModal from '../components/feed/ArticleModal'; +import NiceModal from '@ebay/nice-modal-react'; +import {type Activity} from '../components/activities/ActivityItem'; +import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; +import {useState} from 'react'; + +export function useArticleModal() { + const [articleContent, setArticleContent] = useState(null); + const [articleActor, setArticleActor] = useState(null); + + const handleViewContent = ( + object: ObjectProperties, + contentActor: ActorProperties, + comments: Activity[], + focusReply = false + ) => { + setArticleContent(object); + setArticleActor(contentActor); + NiceModal.show(ArticleModal, {object, actor: contentActor, comments, focusReply}); + }; + + return { + articleContent, + articleActor, + handleViewContent + }; +} diff --git a/apps/admin-x-activitypub/src/utils/content-helpers.ts b/apps/admin-x-activitypub/src/utils/content-helpers.ts new file mode 100644 index 0000000000..febba5ab50 --- /dev/null +++ b/apps/admin-x-activitypub/src/utils/content-helpers.ts @@ -0,0 +1,25 @@ +import {type Activity} from '../components/activities/ActivityItem'; + +export function getContentAuthor(activity: Activity) { + const actor = activity.actor; + const attributedTo = activity.object.attributedTo; + + if (!attributedTo) { + return actor; + } + + if (typeof attributedTo === 'string') { + return actor; + } + + if (Array.isArray(attributedTo)) { + const found = attributedTo.find(item => typeof item !== 'string'); + if (found) { + return found; + } else { + return actor; + } + } + + return attributedTo; +}