diff --git a/app/components/PublicationCard.tsx b/app/components/PublicationCard.tsx new file mode 100644 index 0000000..912e588 --- /dev/null +++ b/app/components/PublicationCard.tsx @@ -0,0 +1,49 @@ +import { useState } from 'react' +import { RssIcon } from '@heroicons/react/24/outline' + +interface Props { + pub: { atUri: string; name: string; url: string; description?: string } + action?: React.ReactNode +} + +export default function PublicationCard({ pub, action }: Props) { + const [copied, setCopied] = useState(false) + + async function handleCopyFeed() { + const feedUrl = `${pub.url.replace(/\/$/, '')}/feed.xml` + try { + await navigator.clipboard.writeText(feedUrl) + setCopied(true) + setTimeout(() => setCopied(false), 2500) + } catch { /* ignore */ } + } + + return ( +
  • +
    +

    {pub.name}

    +

    {new URL(pub.url).host}

    + {pub.description && ( +

    {pub.description}

    + )} + {copied && ( +

    + Feed URL copied — paste into your RSS reader +

    + )} +
    +
    + {new URL(pub.url).origin === window.location.origin && ( + + )} + {action} +
    +
  • + ) +} diff --git a/app/routes/profile.tsx b/app/routes/profile.tsx index 3b91f8a..9cb7e20 100644 --- a/app/routes/profile.tsx +++ b/app/routes/profile.tsx @@ -12,7 +12,7 @@ import PostList from '~/components/PostList' import CenteredMessage from '~/components/CenteredMessage' import PageLayout from '~/components/PageLayout' import Spinner from '~/components/Spinner' -import { RssIcon } from '@heroicons/react/24/outline' +import PublicationCard from '~/components/PublicationCard' import type { Route } from './+types/profile' import { SITE_NAME } from '~/lib/site-config' @@ -31,7 +31,7 @@ export default function Profile() { // publicationAtUri → subscriptionRkey; undefined = not yet loaded const [subscriptionsByPub, setSubscriptionsByPub] = useState | undefined>(undefined) const [loadingPubs, setLoadingPubs] = useState>({}) - const [copiedPubUri, setCopiedPubUri] = useState(null) + useEffect(() => { if (!id) return @@ -129,15 +129,6 @@ export default function Profile() { } } - async function handleCopyFeed(pub: Publication) { - const feedUrl = `${pub.url.replace(/\/$/, '')}/feed.xml` - try { - await navigator.clipboard.writeText(feedUrl) - setCopiedPubUri(pub.atUri) - setTimeout(() => setCopiedPubUri((cur) => (cur === pub.atUri ? null : cur)), 2500) - } catch { /* ignore */ } - } - if (error) { return } @@ -167,53 +158,29 @@ export default function Profile() { const isSubscribed = !!subscriptionsByPub?.[pub.atUri] const isLoading = !!loadingPubs[pub.atUri] return ( -
  • -
    -

    {pub.name}

    -

    {new URL(pub.url).host}

    - {pub.description && ( -

    {pub.description}

    - )} - {copiedPubUri === pub.atUri && ( -

    - Feed URL copied — paste into your RSS reader -

    - )} -
    -
    - {new URL(pub.url).origin === window.location.origin && ( + pub={pub} + action={showSubscribeButtons && ( + isSubscribed ? ( + + ) : ( - )} - {showSubscribeButtons && ( - isSubscribed ? ( - - ) : ( - - ) - )} -
    -
  • + ) + )} + /> ) })} diff --git a/app/routes/subscriptions.tsx b/app/routes/subscriptions.tsx index 26a2a5b..e17487f 100644 --- a/app/routes/subscriptions.tsx +++ b/app/routes/subscriptions.tsx @@ -6,6 +6,7 @@ import CenteredMessage from '~/components/CenteredMessage' import EmptyState from '~/components/EmptyState' import PageLayout from '~/components/PageLayout' import Spinner from '~/components/Spinner' +import PublicationCard from '~/components/PublicationCard' import { SITE_NAME } from '~/lib/site-config' export function meta() { @@ -176,25 +177,19 @@ export default function Subscriptions() { {resolvedPubs.map((pub) => { const isLoading = !!loadingPubs[pub.atUri] return ( -
  • -
    -

    {pub.name}

    -

    {new URL(pub.url).host}

    - {pub.description && ( -

    {pub.description}

    - )} -
    - -
  • + pub={pub} + action={ + + } + /> ) })}