mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Updated ActivityPub Feed and Replies design (#20992)
- Added activity icon for Replies - Updated Replies design - Updated hard-coded Profile values to more realistic ones - Renamed ActivityPub nav item and moved it to the top of the navbar - Added a check for post attachments
This commit is contained in:
parent
625c89e37f
commit
a087e329ed
9 changed files with 51 additions and 26 deletions
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import APAvatar, {AvatarBadge} from './global/APAvatar';
|
||||
import ActivityItem from './activities/ActivityItem';
|
||||
import MainNavigation from './navigation/MainNavigation';
|
||||
import {Button} from '@tryghost/admin-x-design-system';
|
||||
import {Button, NoValueLabel} from '@tryghost/admin-x-design-system';
|
||||
|
||||
import getUsername from '../utils/get-username';
|
||||
import {useBrowseInboxForUser, useBrowseOutboxForUser, useFollowersForUser} from '../MainContent';
|
||||
|
@ -65,7 +65,7 @@ const getExtendedDescription = (activity: Activity): JSX.Element | null => {
|
|||
return (
|
||||
<div
|
||||
dangerouslySetInnerHTML={{__html: activity.object?.content || ''}}
|
||||
className='ml-2 mt-2 text-sm text-grey-600'
|
||||
className='mt-2'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ const getActorUrl = (activity: Activity): string | null => {
|
|||
const getActivityBadge = (activity: Activity): AvatarBadge => {
|
||||
switch (activity.type) {
|
||||
case ACTVITY_TYPE.CREATE:
|
||||
return 'user-fill'; // TODO: Change this
|
||||
return 'comment-fill';
|
||||
case ACTVITY_TYPE.FOLLOW:
|
||||
return 'user-fill';
|
||||
case ACTVITY_TYPE.LIKE:
|
||||
|
@ -171,19 +171,23 @@ const Activities: React.FC<ActivitiesProps> = ({}) => {
|
|||
<MainNavigation title='Activities' />
|
||||
<div className='z-0 flex w-full flex-col items-center'>
|
||||
{activities.length === 0 && (
|
||||
<div className='mt-8 font-bold'>This is an empty state when there are no activities</div>
|
||||
<div className='mt-8'>
|
||||
<NoValueLabel icon='bell'>
|
||||
When other Fediverse users interact with you, you'll see it here.
|
||||
</NoValueLabel>
|
||||
</div>
|
||||
)}
|
||||
{activities.length > 0 && (
|
||||
<div className='mt-8 flex w-full max-w-[560px] flex-col'>
|
||||
{activities?.map(activity => (
|
||||
<ActivityItem key={activity.id} url={getActivityUrl(activity) || getActorUrl(activity)}>
|
||||
<APAvatar author={activity.actor} badge={getActivityBadge(activity)} />
|
||||
<div>
|
||||
<div className='pt-[2px]'>
|
||||
<div className='text-grey-600'>
|
||||
<span className='mr-1 font-bold text-black'>{activity.actor.name}</span>
|
||||
{getUsername(activity.actor)}
|
||||
</div>
|
||||
<div className='text-sm'>{getActivityDescription(activity, activityObjectsMap)}</div>
|
||||
<div className=''>{getActivityDescription(activity, activityObjectsMap)}</div>
|
||||
{getExtendedDescription(activity)}
|
||||
</div>
|
||||
{isFollower(activity.actor.id) === false && (
|
||||
|
|
|
@ -35,7 +35,7 @@ const Profile: React.FC<ProfileProps> = ({}) => {
|
|||
id: 'likes',
|
||||
title: 'Likes',
|
||||
contents: (
|
||||
<div>
|
||||
<div className='ap-likes'>
|
||||
{liked.length === 0 ? (
|
||||
<NoValueLabel icon='heart'>
|
||||
You haven't liked anything yet.
|
||||
|
@ -141,10 +141,10 @@ const Profile: React.FC<ProfileProps> = ({}) => {
|
|||
<div className='inline-flex rounded-lg border-4 border-white'>
|
||||
<APAvatar size='lg' />
|
||||
</div>
|
||||
<Heading className='mt-4' level={3}>John Doe</Heading>
|
||||
<span className='mt-1 text-[1.5rem] text-grey-800'>@index@site.com</span>
|
||||
<p className='mt-3 text-[1.5rem]'>This is a summary/bio/etc which could be kinda long in certain cases but not always, so...</p>
|
||||
<a className='mt-3 block text-[1.5rem] underline' href='#'>www.coolsite.com</a>
|
||||
<Heading className='mt-4' level={3}>Building ActivityPub</Heading>
|
||||
<span className='mt-1 text-[1.5rem] text-grey-800'>@index@activitypub.ghost.org</span>
|
||||
<p className='mt-3 text-[1.5rem]'>Ghost is federating over ActivityPub to become part of the world's largest publishing network</p>
|
||||
<a className='mt-3 block text-[1.5rem] underline' href='https://activitypub.ghost.org'>activitypub.ghost.org</a>
|
||||
<TabView<'posts' | 'likes' | 'following' | 'followers'> containerClassName='mt-6' selectedTab={selectedTab} tabs={tabs} onTabChange={setSelectedTab} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ const ActivityItem: React.FC<ActivityItemProps> = ({children, url = null}) => {
|
|||
|
||||
const Item = (
|
||||
<div className='flex w-full max-w-[560px] flex-col hover:bg-grey-75'>
|
||||
<div className='flex w-full items-center gap-4 border-b border-grey-100 px-2 py-4'>
|
||||
<div className='flex w-full gap-4 border-b border-grey-100 px-2 py-4'>
|
||||
{childrenArray[0]}
|
||||
{childrenArray[1]}
|
||||
{childrenArray[2]}
|
||||
|
|
|
@ -70,7 +70,7 @@ ${image &&
|
|||
};
|
||||
|
||||
const FeedItemDivider: React.FC = () => (
|
||||
<div className="mx-[-32px] my-4 h-px w-[120%] bg-grey-200"></div>
|
||||
<div className="mx-[-32px] my-5 h-px w-[120%] bg-grey-200"></div>
|
||||
);
|
||||
|
||||
const ArticleModal: React.FC<ArticleModalProps> = ({object, actor, comments, allComments}) => {
|
||||
|
|
|
@ -89,10 +89,10 @@ function renderInboxAttachment(object: ObjectProperties) {
|
|||
// }
|
||||
return (
|
||||
<div className='min-w-[160px]'>
|
||||
<div className='relative'>
|
||||
{attachment[0] && <div className='relative'>
|
||||
<img className={`h-[100px] w-[160px] rounded-md object-cover`} src={attachment[0].url} />
|
||||
<div className='absolute bottom-1 right-1 z-10 rounded-full border border-[rgba(255,255,255,0.25)] bg-black px-2 py-0.5 font-semibold text-white'>+ {attachmentCount - 1}</div>
|
||||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ function renderInboxAttachment(object: ObjectProperties) {
|
|||
case 'image/gif':
|
||||
return (
|
||||
<div className='min-w-[160px]'>
|
||||
<img className={`h-[100px] w-[160px] rounded-md object-cover`} src={attachment.url} />
|
||||
{attachment && <img className={`h-[100px] w-[160px] rounded-md object-cover`} src={attachment.url} />}
|
||||
</div>
|
||||
);
|
||||
case 'video/mp4':
|
||||
|
@ -302,7 +302,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
|
|||
</div>
|
||||
<div className={`absolute -inset-x-3 -inset-y-0 z-0 rounded transition-colors`}></div>
|
||||
</div>
|
||||
<div className="mx-[-32px] my-4 h-px w-[120%] bg-grey-200"></div>
|
||||
<div className="mx-[-32px] my-3 h-px w-[120%] bg-grey-200"></div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
@ -312,12 +312,12 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
|
|||
return (
|
||||
<>
|
||||
{object && (
|
||||
<div className={`group/article relative cursor-pointer pt-5`} onClick={onClick}>
|
||||
<div className={`group/article relative cursor-pointer pt-2`} onClick={onClick}>
|
||||
{(type === 'Announce' && object.type === 'Note') && <div className='z-10 mb-2 flex items-center gap-3 text-grey-700'>
|
||||
<div className='z-10 flex w-10 justify-end'><Icon colorClass='text-grey-700' name='reload' size={'sm'}></Icon></div>
|
||||
<span className='z-10'>{actor.name} reposted</span>
|
||||
</div>}
|
||||
<div className={`border-1 z-10 -my-1 grid grid-cols-[auto_1fr] grid-rows-[auto_1fr] gap-x-3 gap-y-2 border-b-grey-200 pb-4`} data-test-activity>
|
||||
<div className={`border-1 z-10 -my-1 grid grid-cols-[auto_1fr] grid-rows-[auto_1fr] gap-x-3 gap-y-2 border-b-grey-200`} data-test-activity>
|
||||
<div className='relative z-10 pt-[3px]'>
|
||||
<APAvatar author={author}/>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ import {ActorProperties} from '@tryghost/admin-x-framework/api/activitypub';
|
|||
import {Icon} from '@tryghost/admin-x-design-system';
|
||||
|
||||
type AvatarSize = 'xs' | 'sm' | 'lg';
|
||||
export type AvatarBadge = 'user-fill' | 'heart-fill' | undefined;
|
||||
export type AvatarBadge = 'user-fill' | 'heart-fill' | 'comment-fill' | undefined;
|
||||
|
||||
interface APAvatarProps {
|
||||
author?: ActorProperties;
|
||||
|
@ -25,6 +25,9 @@ const APAvatar: React.FC<APAvatarProps> = ({author, size, badge}) => {
|
|||
case 'heart-fill':
|
||||
badgeColor = ' bg-red-500';
|
||||
break;
|
||||
case 'comment-fill':
|
||||
badgeColor = ' bg-purple-500';
|
||||
break;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
|
@ -47,7 +50,7 @@ const APAvatar: React.FC<APAvatarProps> = ({author, size, badge}) => {
|
|||
return (
|
||||
<>
|
||||
{author && author.icon?.url ? (
|
||||
<a className='relative z-10 pt-[3px] transition-opacity hover:opacity-80' href={author.url} rel='noopener noreferrer' target='_blank'>
|
||||
<a className='relative z-10 h-10 w-10 pt-[3px] transition-opacity hover:opacity-80' href={author.url} rel='noopener noreferrer' target='_blank'>
|
||||
<img
|
||||
className={imageClass}
|
||||
src={author.icon.url}
|
||||
|
|
|
@ -37,3 +37,17 @@ animation: bump 0.3s ease-in-out;
|
|||
margin-top: 1.5rem !important;
|
||||
}
|
||||
|
||||
.ap-likes .ellipsis::after {
|
||||
content: "…";
|
||||
}
|
||||
|
||||
.ap-likes .invisible {
|
||||
display: inline-block;
|
||||
font-size: 0;
|
||||
height: 0;
|
||||
line-height: 0;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M12 1.34C5.66 1.34 0.5 5.59 0.5 10.81a8.58 8.58 0 0 0 3.18 6.54l-2.3 4.59a0.49 0.49 0 0 0 0.09 0.57 0.5 0.5 0 0 0 0.57 0.1l6.15 -2.86a13.44 13.44 0 0 0 3.81 0.54c6.34 0 11.5 -4.25 11.5 -9.48S18.34 1.34 12 1.34Z" fill="currentColor" stroke-width="1.5px">
|
||||
</path>
|
||||
</svg>
|
After Width: | Height: | Size: 342 B |
|
@ -17,6 +17,11 @@
|
|||
{{#unless this.session.user.isContributor}}
|
||||
<div class="gh-nav-top">
|
||||
<ul class="gh-nav-list gh-nav-main">
|
||||
{{#if (feature "ActivityPub")}}
|
||||
<li>
|
||||
<LinkTo @route="activitypub-x" @current-when="activitypub-x">{{svg-jar "star"}}ActivityPub</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (gh-user-can-admin this.session.user)}}
|
||||
<li class="relative gh-nav-list-home">
|
||||
<LinkTo @route="dashboard" @alt="Dashboard" title="Dashboard" data-test-nav="dashboard">{{svg-jar "house"}} Dashboard</LinkTo>
|
||||
|
@ -128,11 +133,6 @@
|
|||
<LinkTo @route="demo-x" @current-when="demo-x">{{svg-jar "star"}}AdminX Demo</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (feature "ActivityPub")}}
|
||||
<li>
|
||||
<LinkTo @route="activitypub-x" @current-when="activitypub-x">{{svg-jar "star"}}ActivityPub Demo</LinkTo>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
{{#if this.session.user.isOwnerOnly}}
|
||||
|
|
Loading…
Add table
Reference in a new issue