diff --git a/web/src/components/AnnotationCard.jsx b/web/src/components/AnnotationCard.jsx --- a/web/src/components/AnnotationCard.jsx +++ b/web/src/components/AnnotationCard.jsx @@ -27,6 +27,7 @@ } from "lucide-react"; import { HighlightIcon, TrashIcon } from "./Icons"; import ShareMenu from "./ShareMenu"; +import UserMeta from "./UserMeta"; function buildTextFragmentUrl(baseUrl, selector) { if (!selector || selector.type !== "TextQuoteSelector" || !selector.exact) { @@ -173,31 +174,6 @@ } }; - const formatDate = (dateString, simple = true) => { - if (!dateString) return ""; - const date = new Date(dateString); - const now = new Date(); - const diff = now - date; - const minutes = Math.floor(diff / 60000); - const hours = Math.floor(diff / 3600000); - const days = Math.floor(diff / 86400000); - if (minutes < 1) return "just now"; - if (minutes < 60) return `${minutes}m`; - if (hours < 24) return `${hours}h`; - if (days < 7) return `${days}d`; - if (simple) - return date.toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }); - return date.toLocaleString(); - }; - - const authorDisplayName = data.author?.displayName || data.author?.handle; - const authorHandle = data.author?.handle; - const authorAvatar = data.author?.avatar; - const authorDid = data.author?.did; - const marginProfileUrl = authorDid ? `/profile/${authorDid}` : null; const highlightedText = data.selector?.type === "TextQuoteSelector" ? data.selector.exact : null; const fragmentUrl = buildTextFragmentUrl(data.url, data.selector); @@ -245,40 +221,7 @@
- -
- {authorAvatar ? ( - {authorDisplayName} - ) : ( - - {(authorDisplayName || authorHandle || "??") - ?.substring(0, 2) - .toUpperCase()} - - )} -
- -
-
- - {authorDisplayName} - - {authorHandle && ( - - @{authorHandle} - - )} -
-
{formatDate(data.createdAt)}
-
+
@@ -606,60 +549,11 @@ } }; - const formatDate = (dateString, simple = true) => { - if (!dateString) return ""; - const date = new Date(dateString); - const now = new Date(); - const diff = now - date; - const minutes = Math.floor(diff / 60000); - const hours = Math.floor(diff / 3600000); - const days = Math.floor(diff / 86400000); - if (minutes < 1) return "just now"; - if (minutes < 60) return `${minutes}m`; - if (hours < 24) return `${hours}h`; - if (days < 7) return `${days}d`; - if (simple) - return date.toLocaleDateString("en-US", { - month: "short", - day: "numeric", - }); - return date.toLocaleString(); - }; - return (
- -
- {data.author?.avatar ? ( - avatar - ) : ( - ?? - )} -
- -
- - - {data.author?.displayName || "Unknown"} - - -
{formatDate(data.createdAt)}
- {data.author?.handle && ( - - @{data.author.handle} - - )} -
+
diff --git a/web/src/components/BookmarkCard.jsx b/web/src/components/BookmarkCard.jsx --- a/web/src/components/BookmarkCard.jsx +++ b/web/src/components/BookmarkCard.jsx @@ -1,6 +1,5 @@ import { useState, useEffect } from "react"; import { useAuth } from "../context/AuthContext"; -import { Link } from "react-router-dom"; import { normalizeAnnotation, normalizeBookmark, @@ -12,6 +11,7 @@ import { HeartIcon, TrashIcon, BookmarkIcon } from "./Icons"; import { Folder } from "lucide-react"; import ShareMenu from "./ShareMenu"; +import UserMeta from "./UserMeta"; export default function BookmarkCard({ bookmark, @@ -90,21 +90,6 @@ } }; - const formatDate = (dateString) => { - if (!dateString) return ""; - const date = new Date(dateString); - const now = new Date(); - const diff = now - date; - const minutes = Math.floor(diff / 60000); - const hours = Math.floor(diff / 3600000); - const days = Math.floor(diff / 86400000); - if (minutes < 1) return "just now"; - if (minutes < 60) return `${minutes}m`; - if (hours < 24) return `${hours}h`; - if (days < 7) return `${days}d`; - return date.toLocaleDateString("en-US", { month: "short", day: "numeric" }); - }; - let domain = ""; try { if (data.url) domain = new URL(data.url).hostname.replace("www.", ""); @@ -112,50 +97,11 @@ /* ignore */ } - const authorDisplayName = data.author?.displayName || data.author?.handle; - const authorHandle = data.author?.handle; - const authorAvatar = data.author?.avatar; - const authorDid = data.author?.did; - const marginProfileUrl = authorDid ? `/profile/${authorDid}` : null; - return (
- -
- {authorAvatar ? ( - {authorDisplayName} - ) : ( - - {(authorDisplayName || authorHandle || "??") - ?.substring(0, 2) - .toUpperCase()} - - )} -
- -
-
- - {authorDisplayName} - - {authorHandle && ( - - @{authorHandle} - - )} -
-
{formatDate(data.createdAt)}
-
+
diff --git a/web/src/components/UserMeta.jsx b/web/src/components/UserMeta.jsx new file mode 100644 --- /dev/null +++ b/web/src/components/UserMeta.jsx @@ -0,0 +1,63 @@ +import { Link } from "react-router-dom"; + +const formatDate = (dateString, simple = true) => { + if (!dateString) return ""; + const date = new Date(dateString); + const now = new Date(); + const diff = now - date; + const minutes = Math.floor(diff / 60000); + const hours = Math.floor(diff / 3600000); + const days = Math.floor(diff / 86400000); + if (minutes < 1) return "just now"; + if (minutes < 60) return `${minutes}m`; + if (hours < 24) return `${hours}h`; + if (days < 7) return `${days}d`; + if (simple) + return date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + }); + return date.toLocaleString(); +}; + +export default function UserMeta({ author, createdAt }) { + const authorDisplayName = author?.displayName || author?.handle || "Unknown"; + const authorHandle = author?.handle; + const authorAvatar = author?.avatar; + const authorDid = author?.did; + const marginProfileUrl = authorDid ? `/profile/${authorDid}` : "#"; + + return ( + <> + +
+ {authorAvatar ? ( + {authorDisplayName} + ) : ( + + {authorDisplayName?.substring(0, 2).toUpperCase() || "??"} + + )} +
+ +
+
+ + {authorDisplayName} + + {authorHandle && ( + + @{authorHandle} + + )} +
+
{formatDate(createdAt)}
+
+ + ); +}