Skip to content

Commit

Permalink
Merge branch 'main' into captcha-enable-middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-lord authored Jan 27, 2025
2 parents 0dd90c5 + 3e2658b commit ebf7890
Show file tree
Hide file tree
Showing 145 changed files with 1,443 additions and 440 deletions.
2 changes: 1 addition & 1 deletion apps/admin-x-activitypub/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tryghost/admin-x-activitypub",
"version": "0.3.50",
"version": "0.3.54",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
10 changes: 5 additions & 5 deletions apps/admin-x-activitypub/src/components/Inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
</div>
</div>
<div className={`sticky top-[133px] ml-auto w-full max-w-[300px] max-lg:hidden xxxl:sticky xxxl:right-[40px]`}>
<h2 className='mb-2 text-lg font-semibold'>This is your {layout === 'inbox' ? 'inbox' : 'feed'}</h2>
<p className='mb-6 border-b border-grey-200 pb-6 text-grey-700'>You&apos;ll find {layout === 'inbox' ? 'long-form content' : 'short posts and updates'} from the accounts you follow here.</p>
<h2 className='mb-2 text-lg font-semibold'>You might also like</h2>
<h2 className='mb-1.5 text-lg font-semibold'>This is your {layout === 'inbox' ? 'inbox' : 'feed'}</h2>
<p className='mb-6 text-grey-700'>You&apos;ll find {layout === 'inbox' ? 'long-form content' : 'short posts and updates'} from the accounts you follow here.</p>
<h2 className='mb-1 text-lg font-semibold'>You might also like</h2>
{isLoadingSuggested ? (
<LoadingIndicator size="sm" />
) : (
Expand All @@ -154,7 +154,7 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
>
<APAvatar author={actor} />
<div className='flex min-w-0 flex-col'>
<span className='block w-full truncate font-bold text-black'>{getName(actor)}</span>
<span className='block w-full truncate font-semibold text-black'>{getName(actor)}</span>
<span className='block w-full truncate text-sm text-grey-600'>{getUsername(actor)}</span>
</div>
</ActivityItem>
Expand All @@ -165,7 +165,7 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
})}
</ul>
)}
<Button className='mt-4' color='grey' fullWidth={true} label='Explore' onClick={() => updateRoute('search')} />
<Button className='mt-2' color='green' fullWidth={true} label='Explore &rarr;' link={true} onClick={() => updateRoute('search')} />
</div>
</div>
</>
Expand Down
4 changes: 2 additions & 2 deletions apps/admin-x-activitypub/src/components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const AccountSearchResultItem: React.FC<AccountSearchResultItemProps> = ({accoun
}}/>
<div>
<div className='text-grey-600'>
<span className='font-bold text-black'>{account.name} </span>{account.handle}
<span className='font-semibold text-black'>{account.name} </span>{account.handle}
</div>
<div className='text-sm'>{new Intl.NumberFormat().format(account.followerCount)} followers</div>
</div>
Expand Down Expand Up @@ -124,7 +124,7 @@ const SuggestedProfile: React.FC<SuggestedProfileProps> = ({profile, update}) =>
<APAvatar author={profile.actor}/>
<div>
<div className='text-grey-600'>
<span className='font-bold text-black'>{profile.actor.name} </span>{profile.handle}
<span className='font-semibold text-black'>{profile.actor.name} </span>{profile.handle}
</div>
<div className='text-sm'>{new Intl.NumberFormat().format(profile.followerCount)} followers</div>
</div>
Expand Down
60 changes: 51 additions & 9 deletions apps/admin-x-activitypub/src/components/feed/ArticleModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import APAvatar from '../global/APAvatar';
import APReplyBox from '../global/APReplyBox';
import TableOfContents, {TOCItem} from './TableOfContents';
import getReadingTime from '../../utils/get-reading-time';
import {useDebounce} from 'use-debounce';

interface ArticleModalProps {
activityId: string;
Expand Down Expand Up @@ -48,6 +49,7 @@ const ArticleBody: React.FC<{
fontFamily: SelectOption;
onHeadingsExtracted?: (headings: TOCItem[]) => void;
onIframeLoad?: (iframe: HTMLIFrameElement) => void;
onLoadingChange?: (isLoading: boolean) => void;
}> = ({
heading,
image,
Expand All @@ -57,7 +59,8 @@ const ArticleBody: React.FC<{
lineHeight,
fontFamily,
onHeadingsExtracted,
onIframeLoad
onIframeLoad,
onLoadingChange
}) => {
const site = useBrowseSite();
const siteData = site.data?.site;
Expand Down Expand Up @@ -213,7 +216,6 @@ const ArticleBody: React.FC<{
if (iframeWindow && typeof iframeWindow.resizeIframe === 'function') {
iframeWindow.resizeIframe();
} else {
// Fallback: trigger a resize event
const resizeEvent = new Event('resize');
iframeDocument.dispatchEvent(resizeEvent);
}
Expand Down Expand Up @@ -269,6 +271,11 @@ const ArticleBody: React.FC<{
return () => iframe.removeEventListener('load', handleLoad);
}, [onHeadingsExtracted, onIframeLoad]);

// Update parent when loading state changes
useEffect(() => {
onLoadingChange?.(isLoading);
}, [isLoading, onLoadingChange]);

return (
<div className='w-full pb-6'>
<div className='relative'>
Expand Down Expand Up @@ -526,30 +533,66 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
const currentGridWidth = `${parseInt(currentMaxWidth) - 64}px`;

const [readingProgress, setReadingProgress] = useState(0);
const [isLoading, setIsLoading] = useState(true);

// Add debounced version of setReadingProgress
const [debouncedSetReadingProgress] = useDebounce(setReadingProgress, 100);

const PROGRESS_INCREMENT = 5; // Progress is shown in 5% increments (0%, 5%, 10%, etc.)

useEffect(() => {
const container = document.querySelector('.overflow-y-auto');
const article = document.getElementById('object-content');

const handleScroll = () => {
if (isLoading) {
return;
}

if (!container || !article) {
return;
}

const articleRect = article.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();

const isContentShorterThanViewport = articleRect.height <= containerRect.height;

if (isContentShorterThanViewport) {
debouncedSetReadingProgress(100);
return;
}

const scrolledPast = Math.max(0, containerRect.top - articleRect.top);
const totalHeight = (article as HTMLElement).offsetHeight - (container as HTMLElement).offsetHeight;

const rawProgress = Math.min(Math.max((scrolledPast / totalHeight) * 100, 0), 100);
const progress = Math.round(rawProgress / 5) * 5;
const progress = Math.round(rawProgress / PROGRESS_INCREMENT) * PROGRESS_INCREMENT;

setReadingProgress(progress);
debouncedSetReadingProgress(progress);
};

if (isLoading) {
return;
}

const observer = new MutationObserver(handleScroll);
if (article) {
observer.observe(article, {
childList: true,
subtree: true,
characterData: true
});
}

container?.addEventListener('scroll', handleScroll);
return () => container?.removeEventListener('scroll', handleScroll);
}, []);
handleScroll();

return () => {
container?.removeEventListener('scroll', handleScroll);
observer.disconnect();
};
}, [isLoading, debouncedSetReadingProgress]);

const [tocItems, setTocItems] = useState<TOCItem[]>([]);
const [activeHeadingId, setActiveHeadingId] = useState<string | null>(null);
Expand All @@ -575,7 +618,6 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
return;
}

// Use offsetTop for absolute position within the document
const headingOffset = heading.offsetTop;

container.scrollTo({
Expand All @@ -602,7 +644,6 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
return;
}

// Get all heading elements and their positions
const headings = tocItems
.map(item => doc.getElementById(item.id))
.filter((el): el is HTMLElement => el !== null)
Expand Down Expand Up @@ -677,7 +718,7 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
</div>
<div className='relative z-10 flex w-full min-w-0 flex-col overflow-visible text-[1.5rem]'>
<div className='flex w-full'>
<span className='min-w-0 truncate whitespace-nowrap font-bold'>{actor.name}</span>
<span className='min-w-0 truncate whitespace-nowrap font-semibold'>{actor.name}</span>
</div>
<div className='flex w-full'>
<span className='text-grey-700 after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]'>{getUsername(actor)}</span>
Expand Down Expand Up @@ -845,6 +886,7 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
lineHeight={LINE_HEIGHTS[currentLineHeightIndex]}
onHeadingsExtracted={handleHeadingsExtracted}
onIframeLoad={handleIframeLoad}
onLoadingChange={setIsLoading}
/>
<div className='ml-[-7px]'>
<FeedItemStats
Expand Down
Loading

0 comments on commit ebf7890

Please sign in to comment.