From 30713ec56b8b11258a5821fb3d77753b9cbeb587 Mon Sep 17 00:00:00 2001 From: smolgrrr Date: Thu, 26 Oct 2023 19:26:08 +1100 Subject: [PATCH] UI tings --- client/package.json | 2 + client/src/components/Home.tsx | 2 +- .../src/components/PostCard/NewThreadCard.tsx | 2 +- client/src/components/PostCard/PostCard.tsx | 50 +++++- client/src/components/Thread/OPCard.tsx | 158 ++++++++++++++++++ client/src/components/Thread/Thread.tsx | 3 +- 6 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 client/src/components/Thread/OPCard.tsx diff --git a/client/package.json b/client/package.json index 88dbeb1..e5cb027 100644 --- a/client/package.json +++ b/client/package.json @@ -12,9 +12,11 @@ "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "@types/react-swipeable-views": "^0.13.2", + "link-preview-js": "^3.0.5", "nostr-tools": "latest", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-linkify": "^1.0.0-alpha", "react-pull-to-refresh": "^2.0.1", "react-router-dom": "^6.15.0", "react-scripts": "5.0.1", diff --git a/client/src/components/Home.tsx b/client/src/components/Home.tsx index 349355d..206f9d7 100644 --- a/client/src/components/Home.tsx +++ b/client/src/components/Home.tsx @@ -23,7 +23,7 @@ const Home = () => { const filteredAndSortedEvents = uniqEvents .filter(event => - getPow(event.id) > 20 && + getPow(event.id) > 5 && event.kind === 1 && !event.tags.some(tag => tag[0] === 'p') ) diff --git a/client/src/components/PostCard/NewThreadCard.tsx b/client/src/components/PostCard/NewThreadCard.tsx index 97c59d8..4a4d20d 100644 --- a/client/src/components/PostCard/NewThreadCard.tsx +++ b/client/src/components/PostCard/NewThreadCard.tsx @@ -6,7 +6,7 @@ import { minePow } from '../../utils/mine'; import { publish } from '../../utils/relays'; import NostrImg from '../../utils/ImgUpload'; -const difficulty = 20 +const difficulty = 25 const NewThreadCard: React.FC = () => { const [comment, setComment] = useState(""); diff --git a/client/src/components/PostCard/PostCard.tsx b/client/src/components/PostCard/PostCard.tsx index 0441e15..2df689b 100644 --- a/client/src/components/PostCard/PostCard.tsx +++ b/client/src/components/PostCard/PostCard.tsx @@ -6,6 +6,7 @@ import { nip19 } from 'nostr-tools'; import { useEffect, useState } from 'react'; import { subNote } from '../../utils/subscriptions'; import { getMetadata, uniqBy } from '../../utils/utils'; +import { getLinkPreview } from 'link-preview-js'; const colorCombos = [ 'from-red-400 to-yellow-500', @@ -60,11 +61,24 @@ const PostCard = ({ event, metadata, replyCount }: { event: Event, metadata: Eve const numberOfComments = 10; const { comment, file } = parseContent(event); const colorCombo = getColorFromHash(event.pubkey, colorCombos); + const [isExpanded, setIsExpanded] = useState(false); + const truncatedComment = comment.slice(0, 240); let metadataParsed = null; if (metadata !== null) { metadataParsed = getMetadata(metadata); } + + const [linkPreview, setLinkPreview] = useState(null); + + useEffect(() => { + const urls = comment.match(/\bhttps?:\/\/\S+/gi); + if (urls && urls.length > 0) { + getLinkPreview(urls[0]) + .then((preview) => setLinkPreview(preview as LinkPreview)) + .catch((error) => console.error(error)); + } + }, [comment]); return ( <> @@ -92,7 +106,22 @@ const PostCard = ({ event, metadata, replyCount }: { event: Event, metadata: Eve
- {comment} + {isExpanded ? comment : truncatedComment} + {comment.length > 240 && ( + + )} + {linkPreview && linkPreview.images && linkPreview.images.length > 0 && ( +
+ + {linkPreview.title} +
+ {linkPreview.title} +
+
+
+ )}
{file !== "" && (
@@ -109,4 +138,23 @@ const PostCard = ({ event, metadata, replyCount }: { event: Event, metadata: Eve ); }; +interface LinkPreview { + url: string; + title: string; + siteName?: string; + description?: string; + mediaType: string; + contentType?: string; + images: string[]; + videos: { + url?: string; + secureUrl?: string; + type?: string; + width?: string; + height?: string; + [key: string]: any; + }[]; + [key: string]: any; +} + export default PostCard; \ No newline at end of file diff --git a/client/src/components/Thread/OPCard.tsx b/client/src/components/Thread/OPCard.tsx new file mode 100644 index 0000000..5ec6cc7 --- /dev/null +++ b/client/src/components/Thread/OPCard.tsx @@ -0,0 +1,158 @@ +import CardContainer from '../PostCard/CardContainer'; +import { FolderIcon } from '@heroicons/react/24/outline'; +import { parseContent } from '../../utils/content'; +import { Event } from 'nostr-tools'; +import { nip19 } from 'nostr-tools'; +import { useEffect, useState } from 'react'; +import { subNote } from '../../utils/subscriptions'; +import { getMetadata, uniqBy } from '../../utils/utils'; +import { getLinkPreview } from 'link-preview-js'; + +const colorCombos = [ + 'from-red-400 to-yellow-500', + 'from-green-400 to-blue-500', + 'from-purple-400 to-pink-500', + 'from-yellow-400 to-orange-500', + 'from-indigo-400 to-purple-500', + 'from-pink-400 to-red-500', + 'from-blue-400 to-indigo-500', + 'from-orange-400 to-red-500', + 'from-teal-400 to-green-500', + 'from-cyan-400 to-teal-500', + 'from-lime-400 to-green-500', + 'from-amber-400 to-orange-500', + 'from-rose-400 to-pink-500', + 'from-violet-400 to-purple-500', + 'from-sky-400 to-cyan-500' +]; + +const getColorFromHash = (id: string, colors: string[]): string => { + // Create a simple hash from the event.id + let hash = 0; + for (let i = 0; i < id.length; i++) { + hash = (hash << 5) - hash + id.charCodeAt(i); + } + + // Use the hash to pick a color from the colors array + const index = Math.abs(hash) % colors.length; + return colors[index]; +}; + +const timeAgo = (unixTime: number) => { + const seconds = Math.floor((new Date().getTime() / 1000) - unixTime); + + if (seconds < 60) return `now`; + + const minutes = Math.floor(seconds / 60); + if (minutes < 60) return `${minutes}m`; + + const hours = Math.floor(minutes / 60); + if (hours < 24) return `${hours}h`; + + const days = Math.floor(hours / 24); + if (days < 7) return `${days}d`; + + const weeks = Math.floor(days / 7); + return `${weeks}w`; +}; + +const OPCard = ({ event, metadata, replyCount }: { event: Event, metadata: Event | null, replyCount: number}) => { + // Replace 10 with the actual number of comments for each post + const numberOfComments = 10; + const { comment, file } = parseContent(event); + const colorCombo = getColorFromHash(event.pubkey, colorCombos); + const [isExpanded, setIsExpanded] = useState(false); + const truncatedComment = comment.slice(0, 240); + + let metadataParsed = null; + if (metadata !== null) { + metadataParsed = getMetadata(metadata); + } + + const [linkPreview, setLinkPreview] = useState(null); + + useEffect(() => { + const urls = comment.match(/\bhttps?:\/\/\S+/gi); + if (urls && urls.length > 0) { + getLinkPreview(urls[0]) + .then((preview) => setLinkPreview(preview as LinkPreview)) + .catch((error) => console.error(error)); + } + }, [comment]); + + return ( + <> + +
+
+
+ {metadataParsed ? + <> + +
{metadataParsed.name}
+ + : + <> +
+
Anonymous
+ + } +
+
+
{timeAgo(event.created_at)}
+ + {replyCount} +
+
+
+ {isExpanded ? comment : truncatedComment} + {comment.length > 240 && ( + + )} + {linkPreview && linkPreview.images && linkPreview.images.length > 0 && ( + + )} +
+ {file !== "" && ( +
+ +
+ )} +
+ + + ); +}; + +interface LinkPreview { + url: string; + title: string; + siteName?: string; + description?: string; + mediaType: string; + contentType?: string; + images: string[]; + videos: { + url?: string; + secureUrl?: string; + type?: string; + width?: string; + height?: string; + [key: string]: any; + }[]; + [key: string]: any; +} + +export default OPCard; \ No newline at end of file diff --git a/client/src/components/Thread/Thread.tsx b/client/src/components/Thread/Thread.tsx index 8dc94d7..0fd9946 100644 --- a/client/src/components/Thread/Thread.tsx +++ b/client/src/components/Thread/Thread.tsx @@ -12,6 +12,7 @@ import { minePow } from '../../utils/mine'; import { publish } from '../../utils/relays'; import ThreadPost from './ThreadPost'; import ReplyCard from './ReplyCard'; +import OPCard from './OPCard'; const difficulty = 20 @@ -110,7 +111,7 @@ const Thread = () => { <>
- +