diff --git a/src/components/note/base.tsx b/src/components/note/base.tsx index bcfeee32..620de454 100644 --- a/src/components/note/base.tsx +++ b/src/components/note/base.tsx @@ -1,75 +1,24 @@ import NoteMetadata from '@components/note/metadata'; import { NoteParent } from '@components/note/parent'; -import { ImagePreview } from '@components/note/preview/image'; -import { VideoPreview } from '@components/note/preview/video'; -import { NoteQuote } from '@components/note/quote'; import { UserExtend } from '@components/user/extend'; -import { UserMention } from '@components/user/mention'; -import destr from 'destr'; +import { contentParser } from '@utils/parser'; + import { useRouter } from 'next/navigation'; -import { memo, useMemo } from 'react'; -import reactStringReplace from 'react-string-replace'; +import { memo } from 'react'; export const NoteBase = memo(function NoteBase({ event }: { event: any }) { const router = useRouter(); + const content = contentParser(event.content, event.tags); - const content = useMemo(() => { - let parsedContent = event.content; - // get data tags - const tags = destr(event.tags); - // handle urls - parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => { - if (match.match(/\.(jpg|jpeg|gif|png|webp)$/i)) { - // image url - return ; - } else if (match.match(/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/i)) { - // youtube - return ; - } else if (match.match(/\.(mp4|webm)$/i)) { - // video - return ; - } else { - return ( - - {match} - - ); - } - }); - // handle #-hashtags - parsedContent = reactStringReplace(parsedContent, /#(\w+)/g, (match, i) => ( - - #{match} - - )); - // handle mentions - if (tags.length > 0) { - parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match) => { - if (tags[match][0] === 'p') { - // @-mentions - return ; - } else if (tags[match][0] === 'e') { - // note-quotes - return ; - } else { - return; - } - }); - } - - return parsedContent; - }, [event.content, event.tags]); - - const parentNote = useMemo(() => { + const parentNote = () => { if (event.parent_id) { if (event.parent_id !== event.eventId && !event.content.includes('#[0]')) { return ; } } - - return; - }, [event.content, event.eventId, event.parent_id]); + return <>; + }; const openUserPage = (e) => { e.stopPropagation(); @@ -90,14 +39,14 @@ export const NoteBase = memo(function NoteBase({ event }: { event: any }) { onClick={(e) => openThread(e)} className="relative z-10 m-0 flex h-min min-h-min w-full select-text flex-col border-b border-zinc-800 px-3 py-5 hover:bg-black/20" > - {parentNote} + {parentNote()}
openUserPage(e)}>
-
+
{content}
diff --git a/src/components/note/parent.tsx b/src/components/note/parent.tsx index 2a95069e..e5fa208f 100644 --- a/src/components/note/parent.tsx +++ b/src/components/note/parent.tsx @@ -1,29 +1,24 @@ import NoteMetadata from '@components/note/metadata'; -import { ImagePreview } from '@components/note/preview/image'; -import { VideoPreview } from '@components/note/preview/video'; -import { NoteQuote } from '@components/note/quote'; import { RelayContext } from '@components/relaysProvider'; import { UserExtend } from '@components/user/extend'; -import { UserMention } from '@components/user/mention'; +import { contentParser } from '@utils/parser'; import { getParentID } from '@utils/transform'; import useLocalStorage from '@rehooks/local-storage'; -import destr from 'destr'; -import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; -import reactStringReplace from 'react-string-replace'; +import { memo, useCallback, useContext, useEffect, useRef, useState } from 'react'; export const NoteParent = memo(function NoteParent({ id }: { id: string }) { const [pool, relays]: any = useContext(RelayContext); const [activeAccount]: any = useLocalStorage('activeAccount', {}); const [event, setEvent] = useState(null); - const unsubscribe = useRef(null); + const content = event ? contentParser(event?.content, event.tags) : ''; + const fetchEvent = useCallback(async () => { const { createNote } = await import('@utils/bindings'); - unsubscribe.current = pool.subscribe( [ { @@ -50,7 +45,7 @@ export const NoteParent = memo(function NoteParent({ id }: { id: string }) { account_id: activeAccount.id, }).catch(console.error); }, - 100, + undefined, undefined, { unsubscribeOnEose: true, @@ -81,56 +76,6 @@ export const NoteParent = memo(function NoteParent({ id }: { id: string }) { }; }, [checkNoteExist]); - const content = useMemo(() => { - let parsedContent = event ? event.content : null; - - if (parsedContent !== null) { - // get data tags - const tags = destr(event.tags); - // handle urls - parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => { - if (match.match(/\.(jpg|jpeg|gif|png|webp)$/i)) { - // image url - return ; - } else if (match.match(/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/i)) { - // youtube - return ; - } else if (match.match(/\.(mp4|webm)$/i)) { - // video - return ; - } else { - return ( - - {match} - - ); - } - }); - // handle #-hashtags - parsedContent = reactStringReplace(parsedContent, /#(\w+)/g, (match, i) => ( - - #{match} - - )); - // handle mentions - if (tags.length > 0) { - parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match, i) => { - if (tags[match][0] === 'p') { - // @-mentions - return ; - } else if (tags[match][0] === 'e') { - // note-quotes - return ; - } else { - return; - } - }); - } - } - - return parsedContent; - }, [event]); - if (event) { return (
@@ -139,7 +84,7 @@ export const NoteParent = memo(function NoteParent({ id }: { id: string }) {
-
+
{content}
diff --git a/src/components/note/placeholder.tsx b/src/components/note/placeholder.tsx index a5fb3841..5c87d613 100644 --- a/src/components/note/placeholder.tsx +++ b/src/components/note/placeholder.tsx @@ -1,8 +1,6 @@ -import { memo } from 'react'; - -export const Placeholder = memo(function Placeholder() { +export const Placeholder = () => { return ( -
+
@@ -27,4 +25,4 @@ export const Placeholder = memo(function Placeholder() {
); -}); +}; diff --git a/src/components/note/quote.tsx b/src/components/note/quote.tsx index b1a0761f..4e91f61b 100644 --- a/src/components/note/quote.tsx +++ b/src/components/note/quote.tsx @@ -1,22 +1,21 @@ import { RelayContext } from '@components/relaysProvider'; import { UserExtend } from '@components/user/extend'; -import { UserMention } from '@components/user/mention'; +import { contentParser } from '@utils/parser'; import { getParentID } from '@utils/transform'; import useLocalStorage from '@rehooks/local-storage'; -import destr from 'destr'; -import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; -import reactStringReplace from 'react-string-replace'; +import { memo, useCallback, useContext, useEffect, useRef, useState } from 'react'; export const NoteQuote = memo(function NoteQuote({ id }: { id: string }) { const [pool, relays]: any = useContext(RelayContext); const [activeAccount]: any = useLocalStorage('activeAccount', {}); const [event, setEvent] = useState(null); - const unsubscribe = useRef(null); + const content = contentParser(event.content, event.tags); + const fetchEvent = useCallback(async () => { const { createNote } = await import('@utils/bindings'); @@ -46,7 +45,7 @@ export const NoteQuote = memo(function NoteQuote({ id }: { id: string }) { account_id: activeAccount.id, }).catch(console.error); }, - 100, + undefined, undefined, { unsubscribeOnEose: true, @@ -77,40 +76,6 @@ export const NoteQuote = memo(function NoteQuote({ id }: { id: string }) { }; }, [checkNoteExist]); - const content = useMemo(() => { - let parsedContent = event ? event.content : null; - - if (parsedContent !== null) { - // get data tags - const tags = destr(event.tags); - // handle urls - parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => ( - - {match} - - )); - // handle #-hashtags - parsedContent = reactStringReplace(parsedContent, /#(\w+)/g, (match, i) => ( - - #{match} - - )); - // handle mentions - if (tags.length > 0) { - parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match, i) => { - if (tags[match][0] === 'p') { - // @-mentions - return ; - } else { - return; - } - }); - } - } - - return parsedContent; - }, [event]); - if (event) { return (
@@ -118,7 +83,7 @@ export const NoteQuote = memo(function NoteQuote({ id }: { id: string }) {
-
+
{content}
diff --git a/src/components/note/rootNote.tsx b/src/components/note/rootNote.tsx index e3153ea2..515fc1f1 100644 --- a/src/components/note/rootNote.tsx +++ b/src/components/note/rootNote.tsx @@ -1,64 +1,14 @@ import NoteMetadata from '@components/note/metadata'; -import { ImagePreview } from '@components/note/preview/image'; -import { VideoPreview } from '@components/note/preview/video'; -import { NoteQuote } from '@components/note/quote'; import { UserExtend } from '@components/user/extend'; -import { UserMention } from '@components/user/mention'; -import destr from 'destr'; +import { contentParser } from '@utils/parser'; + import { useRouter } from 'next/navigation'; -import { memo, useMemo } from 'react'; -import reactStringReplace from 'react-string-replace'; +import { memo } from 'react'; export const RootNote = memo(function RootNote({ event }: { event: any }) { const router = useRouter(); - - const content = useMemo(() => { - let parsedContent = event.content; - // get data tags - const tags = destr(event.tags); - // handle urls - parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => { - if (match.match(/\.(jpg|jpeg|gif|png|webp)$/i)) { - // image url - return ; - } else if (match.match(/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/i)) { - // youtube - return ; - } else if (match.match(/\.(mp4|webm)$/i)) { - // video - return ; - } else { - return ( - - {match} - - ); - } - }); - // handle #-hashtags - parsedContent = reactStringReplace(parsedContent, /#(\w+)/g, (match, i) => ( - - #{match} - - )); - // handle mentions - if (tags.length > 0) { - parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match) => { - if (tags[match][0] === 'p') { - // @-mentions - return ; - } else if (tags[match][0] === 'e') { - // note-quotes - return ; - } else { - return; - } - }); - } - - return parsedContent; - }, [event.content, event.tags]); + const content = contentParser(event.content, event.tags); const openUserPage = (e) => { e.stopPropagation(); @@ -68,7 +18,7 @@ export const RootNote = memo(function RootNote({ event }: { event: any }) { const openThread = (e) => { const selection = window.getSelection(); if (selection.toString().length === 0) { - router.push(`/newsfeed/${event.parent_id}`); + router.push(`/newsfeed/${event.id}`); } else { e.stopPropagation(); } @@ -77,21 +27,21 @@ export const RootNote = memo(function RootNote({ event }: { event: any }) { return (
openThread(e)} className="relative z-10 flex flex-col">
openUserPage(e)}> - +
-
+
{content}
e.stopPropagation()} className="mt-5 pl-[52px]">
diff --git a/src/utils/parser.tsx b/src/utils/parser.tsx new file mode 100644 index 00000000..3c9944a9 --- /dev/null +++ b/src/utils/parser.tsx @@ -0,0 +1,55 @@ +import { ImagePreview } from '@components/note/preview/image'; +import { VideoPreview } from '@components/note/preview/video'; +import { NoteQuote } from '@components/note/quote'; +import { UserMention } from '@components/user/mention'; + +import destr from 'destr'; +import reactStringReplace from 'react-string-replace'; + +export const contentParser = (noteContent, noteTags) => { + let parsedContent = noteContent; + + // get data tags + const tags = destr(noteTags); + // handle urls + parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => { + if (match.match(/\.(jpg|jpeg|gif|png|webp)$/i)) { + // image url + return ; + } else if (match.match(/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/i)) { + // youtube + return ; + } else if (match.match(/\.(mp4|webm)$/i)) { + // video + return ; + } else { + return ( + + {match} + + ); + } + }); + // handle #-hashtags + parsedContent = reactStringReplace(parsedContent, /#(\w+)/g, (match, i) => ( + + #{match} + + )); + // handle mentions + if (tags.length > 0) { + parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match) => { + if (tags[match][0] === 'p') { + // @-mentions + return ; + } else if (tags[match][0] === 'e') { + // note-quotes + return ; + } else { + return; + } + }); + } + + return parsedContent; +};