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={
+
+ }
+ />
)
})}