feat(short posts): add recent posts with image preview
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m16s
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m16s
This commit is contained in:
parent
840247f0b7
commit
78e679b7b0
@ -1,7 +1,7 @@
|
|||||||
import { FALLBACK_PROFILE_IMAGE } from 'constants.ts'
|
import { FALLBACK_PROFILE_IMAGE } from 'constants.ts'
|
||||||
import { Event, Filter, kinds, nip19, UnsignedEvent } from 'nostr-tools'
|
import { Event, Filter, kinds, nip19, UnsignedEvent } from 'nostr-tools'
|
||||||
import { QRCodeSVG } from 'qrcode.react'
|
import { QRCodeSVG } from 'qrcode.react'
|
||||||
import { Fragment, useMemo, useState } from 'react'
|
import { Fragment, useEffect, useMemo, useState } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import {
|
import {
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
useDidMount,
|
useDidMount,
|
||||||
useNDKContext
|
useNDKContext
|
||||||
} from '../hooks'
|
} from '../hooks'
|
||||||
import { appRoutes, getProfilePageRoute } from '../routes'
|
import { appRoutes, getFeedNotePageRoute, getProfilePageRoute } from '../routes'
|
||||||
import '../styles/author.css'
|
import '../styles/author.css'
|
||||||
import '../styles/innerPage.css'
|
import '../styles/innerPage.css'
|
||||||
import '../styles/socialPosts.css'
|
import '../styles/socialPosts.css'
|
||||||
@ -18,6 +18,8 @@ import { UserRelaysType } from '../types'
|
|||||||
import {
|
import {
|
||||||
copyTextToClipboard,
|
copyTextToClipboard,
|
||||||
hexToNpub,
|
hexToNpub,
|
||||||
|
isValidImageUrl,
|
||||||
|
isValidUrl,
|
||||||
log,
|
log,
|
||||||
LogType,
|
LogType,
|
||||||
now,
|
now,
|
||||||
@ -26,8 +28,12 @@ import {
|
|||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { LoadingSpinner } from './LoadingSpinner'
|
import { LoadingSpinner } from './LoadingSpinner'
|
||||||
import { ZapPopUp } from './Zap'
|
import { ZapPopUp } from './Zap'
|
||||||
import placeholder from '../assets/img/DEGMods Placeholder Img.png'
|
import {
|
||||||
import { NDKEvent, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk'
|
NDKEvent,
|
||||||
|
NDKFilter,
|
||||||
|
NDKKind,
|
||||||
|
NDKSubscriptionCacheUsage
|
||||||
|
} from '@nostr-dev-kit/ndk'
|
||||||
import { useProfile } from 'hooks/useProfile'
|
import { useProfile } from 'hooks/useProfile'
|
||||||
import { createPortal } from 'react-dom'
|
import { createPortal } from 'react-dom'
|
||||||
|
|
||||||
@ -36,12 +42,60 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ProfileSection = ({ pubkey }: Props) => {
|
export const ProfileSection = ({ pubkey }: Props) => {
|
||||||
|
const { ndk } = useNDKContext()
|
||||||
|
const profile = useProfile(pubkey, {
|
||||||
|
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
|
||||||
|
})
|
||||||
|
const displayName =
|
||||||
|
profile?.displayName || profile?.name || '[name not set up]'
|
||||||
|
const [posts, setPosts] = useState<Post[]>([])
|
||||||
|
useEffect(() => {
|
||||||
|
const filter: NDKFilter = {
|
||||||
|
authors: [pubkey],
|
||||||
|
kinds: [NDKKind.Text],
|
||||||
|
limit: 10
|
||||||
|
}
|
||||||
|
ndk
|
||||||
|
.fetchEvents(filter, {
|
||||||
|
closeOnEose: true,
|
||||||
|
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
|
||||||
|
})
|
||||||
|
.then((ndkEventSet) => {
|
||||||
|
const ndkEvents = Array.from(ndkEventSet)
|
||||||
|
const posts: Post[] = ndkEvents
|
||||||
|
.sort((a, b) => (b.created_at ?? 0) - (a.created_at ?? 0))
|
||||||
|
.map((ndkEvent) => ({
|
||||||
|
content: ndkEvent.content,
|
||||||
|
link: getFeedNotePageRoute(ndkEvent.encode()),
|
||||||
|
name: displayName
|
||||||
|
}))
|
||||||
|
posts.splice(5)
|
||||||
|
for (const post of posts) {
|
||||||
|
const imageUrls = post.content.match(
|
||||||
|
new RegExp(
|
||||||
|
/(?:https?:\/\/|www\.)(?:[a-zA-Z0-9.-]+\.[a-zA-Z]+(?::\d+)?)(?:[/?#][\p{L}\p{N}\p{M}&.-/?=#\-@%+_,:!~*]*)?/gu
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (imageUrls) {
|
||||||
|
for (const url of imageUrls) {
|
||||||
|
if (isValidUrl(url) && isValidImageUrl(url)) {
|
||||||
|
post.imageUrl = url
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setPosts(posts)
|
||||||
|
})
|
||||||
|
}, [displayName, ndk, pubkey])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='IBMSMSplitMainSmallSide'>
|
<div className='IBMSMSplitMainSmallSide'>
|
||||||
<div className='IBMSMSplitMainSmallSideSecWrapper'>
|
<div className='IBMSMSplitMainSmallSideSecWrapper'>
|
||||||
<div className='IBMSMSplitMainSmallSideSec'>
|
<div className='IBMSMSplitMainSmallSideSec'>
|
||||||
<Profile pubkey={pubkey} />
|
<Profile pubkey={pubkey} />
|
||||||
</div>
|
</div>
|
||||||
|
{posts.length > 0 && (
|
||||||
<div className='IBMSMSplitMainSmallSideSec'>
|
<div className='IBMSMSplitMainSmallSideSec'>
|
||||||
<div className='IBMSMSMSSS_ShortPosts'>
|
<div className='IBMSMSMSSS_ShortPosts'>
|
||||||
{posts.map((post, index) => (
|
{posts.map((post, index) => (
|
||||||
@ -85,6 +139,7 @@ export const ProfileSection = ({ pubkey }: Props) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -222,25 +277,6 @@ interface Post {
|
|||||||
imageUrl?: string
|
imageUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const posts: Post[] = [
|
|
||||||
{
|
|
||||||
name: 'User name',
|
|
||||||
link: `feed-note.html`,
|
|
||||||
content: `user text, this is a long string of temporary text that would be replaced with the user post from their short posts`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User name',
|
|
||||||
link: 'feed-note.html',
|
|
||||||
content: `user text, this is a long string of temporary text that would be replaced with the user post from their short posts`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User name',
|
|
||||||
link: `feed-note.html`,
|
|
||||||
content: `user text, this is a long string of temporary text that would be replaced with the user post from their short posts`,
|
|
||||||
imageUrl: placeholder
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
type QRButtonWithPopUpProps = {
|
type QRButtonWithPopUpProps = {
|
||||||
nprofile: string
|
nprofile: string
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user