feat(feed): add feed outlet, note action and types

This commit is contained in:
en 2025-02-14 13:11:12 +01:00
parent eb27eabcc6
commit 27cd22f47b
5 changed files with 112 additions and 2 deletions

85
src/pages/feed/action.ts Normal file
View File

@ -0,0 +1,85 @@
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk'
import { NDKContextType } from 'contexts/NDKContext'
import { ActionFunctionArgs, redirect } from 'react-router-dom'
import { toast } from 'react-toastify'
import { getFeedNotePageRoute } from 'routes'
import { store } from 'store'
import { NoteSubmitForm, NoteSubmitFormErrors } from 'types'
import { log, LogType, now } from 'utils'
export const feedPostRouteAction =
(ndkContext: NDKContextType) =>
async ({ request }: ActionFunctionArgs) => {
const userState = store.getState().user
let hexPubkey: string
if (userState.auth && userState.user?.pubkey) {
hexPubkey = userState.user.pubkey as string
} else {
try {
hexPubkey = (await window.nostr?.getPublicKey()) as string
} catch (error) {
if (error instanceof Error) {
log(true, LogType.Error, 'Failed to get public key.', error)
}
toast.error('Failed to get public key.')
return null
}
}
if (!hexPubkey) {
toast.error('Could not get pubkey')
return null
}
const formSubmit = (await request.json()) as NoteSubmitForm
const formErrors = validateFormData(formSubmit)
if (Object.keys(formErrors).length) return formErrors
const content = decodeURIComponent(formSubmit.content!)
const currentTimeStamp = now()
const ndkEvent = new NDKEvent(ndkContext.ndk, {
kind: NDKKind.Text,
created_at: currentTimeStamp,
content: content,
tags: [],
pubkey: hexPubkey
})
try {
await ndkEvent.generateTags()
if (formSubmit.nsfw) ndkEvent.tags.push(['L', 'content-warning'])
ndkEvent.tags.push(['L', 'source'])
ndkEvent.tags.push(['l', window.location.host, 'source'])
ndkEvent.tags.push(['client', 'DEG Mods'])
await ndkEvent.sign()
const note1 = ndkEvent.encode()
const publishedOnRelays = await ndkEvent.publish()
if (publishedOnRelays.size === 0) {
toast.error('Failed to publish note on any relay')
return null
} else {
toast.success('Note published successfully')
return redirect(getFeedNotePageRoute(note1))
}
} catch (error) {
log(true, LogType.Error, 'Failed to publish note', error)
toast.error('Failed to publish note')
return null
}
}
const validateFormData = (formSubmit: NoteSubmitForm): NoteSubmitFormErrors => {
const errors: NoteSubmitFormErrors = {}
if (!formSubmit.content.trim()) {
errors.content = 'Content is required'
}
return errors
}

View File

@ -4,9 +4,12 @@ import { FeedTabBlogs } from './FeedTabBlogs'
import { FeedTabMods } from './FeedTabMods'
import { FeedTabPosts } from './FeedTabPosts'
import { FeedFilter } from 'components/Filters/FeedFilter'
import { Outlet, useParams } from 'react-router-dom'
export const FeedPage = () => {
const [tab, setTab] = useState(0)
const { note } = useParams()
// Open posts tab if note is present
const [tab, setTab] = useState(note ? 2 : 0)
return (
<>
@ -17,6 +20,8 @@ export const FeedPage = () => {
{tab === 0 && <FeedTabMods />}
{tab === 1 && <FeedTabBlogs />}
{tab === 2 && <FeedTabPosts />}
<Outlet key={note} />
</>
)
}

View File

@ -33,6 +33,7 @@ import { BackupPage } from 'pages/backup'
import { SupportersPage } from 'pages/supporters'
import { commentsLoader } from 'loaders/comment'
import { CommentsPopup } from 'components/comment/CommentsPopup'
import { feedPostRouteAction } from 'pages/feed/action'
export const appRoutes = {
home: '/',
@ -56,6 +57,7 @@ export const appRoutes = {
settingsAdmin: '/settings-admin',
profile: '/profile/:nprofile?',
feed: '/feed',
note: '/feed/:note',
notifications: '/notifications',
backup: '/backup',
supporters: '/supporters'
@ -76,6 +78,9 @@ export const getBlogPageRoute = (eventId: string) =>
export const getProfilePageRoute = (nprofile: string) =>
appRoutes.profile.replace(':nprofile', nprofile)
export const getFeedNotePageRoute = (note: string) =>
appRoutes.note.replace(':note', note)
export const routerWithNdkContext = (context: NDKContextType) =>
createBrowserRouter([
{
@ -199,7 +204,15 @@ export const routerWithNdkContext = (context: NDKContextType) =>
{
path: appRoutes.feed,
element: <FeedPage />,
loader: feedPageLoader(context)
loader: feedPageLoader(context),
action: feedPostRouteAction(context),
children: [
{
path: ':note',
element: <CommentsPopup />,
loader: commentsLoader(context)
}
]
},
{
path: appRoutes.notifications,

View File

@ -8,3 +8,4 @@ export * from './category'
export * from './popup'
export * from './errors'
export * from './comments'
export * from './note'

6
src/types/note.ts Normal file
View File

@ -0,0 +1,6 @@
export interface NoteSubmitForm {
content: string
nsfw: boolean
}
export interface NoteSubmitFormErrors extends Partial<NoteSubmitForm> {}