0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2024-12-30 22:34:01 -05:00
Djordje Vlaisavljevic 2024-10-28 14:26:35 +01:00
parent bf714ac22f
commit 3cbc28bdbb
4 changed files with 94 additions and 48 deletions

View file

@ -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<InboxProps> = ({}) => {
const [, setArticleContent] = useState<ObjectProperties | null>(null);
const [, setArticleActor] = useState<ActorProperties | null>(null);
const {handleViewContent} = useArticleModal();
const {layout} = useLayout();
const {
@ -45,36 +44,6 @@ const Inbox: React.FC<InboxProps> = ({}) => {
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<IntersectionObserver | null>(null);
@ -123,7 +92,8 @@ const Inbox: React.FC<InboxProps> = ({}) => {
onClick={() => handleViewContent(
activity.object,
getContentAuthor(activity),
activity.object.replies
activity.object.replies,
false
)}
>
<FeedItem

View file

@ -7,9 +7,9 @@ import React, {useEffect, useRef, useState} from 'react';
import getUsername from '../utils/get-username';
import {ActorProperties} from '@tryghost/admin-x-framework/api/activitypub';
import ArticleModal from './feed/ArticleModal';
import ViewProfileModal from './global/ViewProfileModal';
import {Button, Heading, List, NoValueLabel, Tab, TabView} from '@tryghost/admin-x-design-system';
import {useArticleModal} from '../hooks/useArticleModal';
import {
useFollowersCountForUser,
useFollowersExpandedForUser,
@ -73,12 +73,36 @@ const Profile: React.FC<ProfileProps> = ({}) => {
});
};
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<ProfileProps> = ({}) => {
<li
key={activity.id}
data-test-view-article
onClick={() => handlePostClick(activity)}
onClick={() => handlePostClick(activity, false)}
>
<FeedItem
actor={activity.object?.attributedTo || activity.actor}
layout={layout}
object={activity.object}
type={activity.type}
onCommentClick={() => {}}
onCommentClick={() => handlePostClick(activity, true)}
/>
{index < posts.length - 1 && (
<div className="h-px w-full bg-grey-200"></div>
@ -142,14 +166,14 @@ const Profile: React.FC<ProfileProps> = ({}) => {
<li
key={activity.id}
data-test-view-article
onClick={() => handlePostClick(activity)}
onClick={() => handlePostClick(activity, false)}
>
<FeedItem
actor={activity.object?.attributedTo || activity.actor}
layout={layout}
object={Object.assign({}, activity.object, {liked: true})}
type={activity.type}
onCommentClick={() => {}}
onCommentClick={() => handlePostClick(activity, true)}
/>
{index < liked.length - 1 && (
<div className="h-px w-full bg-grey-200"></div>

View file

@ -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<ObjectProperties | null>(null);
const [articleActor, setArticleActor] = useState<ActorProperties | null>(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
};
}

View file

@ -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;
}