feat: automatically add nostr: prefix to nip19 stuff

This commit is contained in:
codytseng
2025-03-14 10:35:39 +08:00
parent 1c08bc067d
commit eb15544195
4 changed files with 49 additions and 18 deletions

View File

@@ -13,6 +13,7 @@ import PostOptions from './PostOptions'
import Preview from './Preview' import Preview from './Preview'
import SendOnlyToSwitch from './SendOnlyToSwitch' import SendOnlyToSwitch from './SendOnlyToSwitch'
import Uploader from './Uploader' import Uploader from './Uploader'
import { preprocessContent } from './utils'
export default function NormalPostContent({ export default function NormalPostContent({
defaultContent = '', defaultContent = '',
@@ -27,6 +28,7 @@ export default function NormalPostContent({
const { toast } = useToast() const { toast } = useToast()
const { publish, checkLogin } = useNostr() const { publish, checkLogin } = useNostr()
const [content, setContent] = useState('') const [content, setContent] = useState('')
const [processedContent, setProcessedContent] = useState('')
const [pictureInfos, setPictureInfos] = useState<{ url: string; tags: string[][] }[]>([]) const [pictureInfos, setPictureInfos] = useState<{ url: string; tags: string[][] }[]>([])
const [posting, setPosting] = useState(false) const [posting, setPosting] = useState(false)
const [showMoreOptions, setShowMoreOptions] = useState(false) const [showMoreOptions, setShowMoreOptions] = useState(false)
@@ -39,9 +41,10 @@ export default function NormalPostContent({
const canPost = !!content && !posting const canPost = !!content && !posting
useEffect(() => { useEffect(() => {
const cachedContent = postContentCache.getNormalPostCache({ defaultContent, parentEvent }) const cached = postContentCache.getNormalPostCache({ defaultContent, parentEvent })
if (cachedContent) { if (cached) {
setContent(cachedContent) setContent(cached.content || '')
setPictureInfos(cached.pictureInfos || [])
} }
if (defaultContent) { if (defaultContent) {
setCursorOffset(defaultContent.length) setCursorOffset(defaultContent.length)
@@ -52,9 +55,10 @@ export default function NormalPostContent({
}, [defaultContent, parentEvent]) }, [defaultContent, parentEvent])
useEffect(() => { useEffect(() => {
setProcessedContent(preprocessContent(content))
if (!initializedRef.current) return if (!initializedRef.current) return
postContentCache.setNormalPostCache({ defaultContent, parentEvent }, content) postContentCache.setNormalPostCache({ defaultContent, parentEvent }, content, pictureInfos)
}, [content]) }, [content, pictureInfos])
const post = async (e: React.MouseEvent) => { const post = async (e: React.MouseEvent) => {
e.stopPropagation() e.stopPropagation()
@@ -68,11 +72,11 @@ export default function NormalPostContent({
try { try {
const draftEvent = const draftEvent =
parentEvent && parentEvent.kind !== kinds.ShortTextNote parentEvent && parentEvent.kind !== kinds.ShortTextNote
? await createCommentDraftEvent(content, parentEvent, pictureInfos, mentions, { ? await createCommentDraftEvent(processedContent, parentEvent, pictureInfos, mentions, {
addClientTag, addClientTag,
protectedEvent: !!specifiedRelayUrls protectedEvent: !!specifiedRelayUrls
}) })
: await createShortTextNoteDraftEvent(content, pictureInfos, mentions, { : await createShortTextNoteDraftEvent(processedContent, pictureInfos, mentions, {
parentEvent, parentEvent,
addClientTag, addClientTag,
protectedEvent: !!specifiedRelayUrls protectedEvent: !!specifiedRelayUrls
@@ -117,7 +121,7 @@ export default function NormalPostContent({
placeholder={t('Write something...')} placeholder={t('Write something...')}
cursorOffset={cursorOffset} cursorOffset={cursorOffset}
/> />
{content && <Preview content={content} />} {processedContent && <Preview content={processedContent} />}
<SendOnlyToSwitch <SendOnlyToSwitch
parentEvent={parentEvent} parentEvent={parentEvent}
specifiedRelayUrls={specifiedRelayUrls} specifiedRelayUrls={specifiedRelayUrls}
@@ -150,7 +154,7 @@ export default function NormalPostContent({
</div> </div>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<Mentions <Mentions
content={content} content={processedContent}
parentEvent={parentEvent} parentEvent={parentEvent}
mentions={mentions} mentions={mentions}
setMentions={setMentions} setMentions={setMentions}

View File

@@ -13,12 +13,14 @@ import Mentions from './Mentions'
import PostOptions from './PostOptions' import PostOptions from './PostOptions'
import SendOnlyToSwitch from './SendOnlyToSwitch' import SendOnlyToSwitch from './SendOnlyToSwitch'
import Uploader from './Uploader' import Uploader from './Uploader'
import { preprocessContent } from './utils'
export default function PicturePostContent({ close }: { close: () => void }) { export default function PicturePostContent({ close }: { close: () => void }) {
const { t } = useTranslation() const { t } = useTranslation()
const { toast } = useToast() const { toast } = useToast()
const { publish, checkLogin } = useNostr() const { publish, checkLogin } = useNostr()
const [content, setContent] = useState('') const [content, setContent] = useState('')
const [processedContent, setProcessedContent] = useState('')
const [pictureInfos, setPictureInfos] = useState<{ url: string; tags: string[][] }[]>([]) const [pictureInfos, setPictureInfos] = useState<{ url: string; tags: string[][] }[]>([])
const [posting, setPosting] = useState(false) const [posting, setPosting] = useState(false)
const [showMoreOptions, setShowMoreOptions] = useState(false) const [showMoreOptions, setShowMoreOptions] = useState(false)
@@ -38,6 +40,7 @@ export default function PicturePostContent({ close }: { close: () => void }) {
}, []) }, [])
useEffect(() => { useEffect(() => {
setProcessedContent(preprocessContent(content))
if (!initializedRef.current) return if (!initializedRef.current) return
postContentCache.setPicturePostCache(content, pictureInfos) postContentCache.setPicturePostCache(content, pictureInfos)
}, [content, pictureInfos]) }, [content, pictureInfos])
@@ -55,10 +58,15 @@ export default function PicturePostContent({ close }: { close: () => void }) {
if (!pictureInfos.length) { if (!pictureInfos.length) {
throw new Error(t('Picture note requires images')) throw new Error(t('Picture note requires images'))
} }
const draftEvent = await createPictureNoteDraftEvent(content, pictureInfos, mentions, { const draftEvent = await createPictureNoteDraftEvent(
processedContent,
pictureInfos,
mentions,
{
addClientTag, addClientTag,
protectedEvent: !!specifiedRelayUrls protectedEvent: !!specifiedRelayUrls
}) }
)
await publish(draftEvent, { specifiedRelayUrls }) await publish(draftEvent, { specifiedRelayUrls })
setContent('') setContent('')
setPictureInfos([]) setPictureInfos([])
@@ -117,7 +125,7 @@ export default function PicturePostContent({ close }: { close: () => void }) {
<ChevronDown className={`transition-transform ${showMoreOptions ? 'rotate-180' : ''}`} /> <ChevronDown className={`transition-transform ${showMoreOptions ? 'rotate-180' : ''}`} />
</Button> </Button>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<Mentions content={content} mentions={mentions} setMentions={setMentions} /> <Mentions content={processedContent} mentions={mentions} setMentions={setMentions} />
<div className="flex gap-2 items-center max-sm:hidden"> <div className="flex gap-2 items-center max-sm:hidden">
<Button <Button
variant="secondary" variant="secondary"

View File

@@ -0,0 +1,6 @@
export function preprocessContent(content: string) {
const regex = /(?<=^|\s)(nevent|naddr|nprofile|npub)[a-zA-Z0-9]+/g
return content.replace(regex, (match) => {
return `nostr:${match}`
})
}

View File

@@ -3,7 +3,13 @@ import { Event } from 'nostr-tools'
class PostContentCacheService { class PostContentCacheService {
static instance: PostContentCacheService static instance: PostContentCacheService
private normalPostCache: Map<string, string> = new Map() private normalPostCache: Map<
string,
{
content: string
pictureInfos: { url: string; tags: string[][] }[]
}
> = new Map()
private picturePostCache: { private picturePostCache: {
content: string content: string
pictureInfos: { url: string; tags: string[][] }[] pictureInfos: { url: string; tags: string[][] }[]
@@ -21,15 +27,22 @@ class PostContentCacheService {
parentEvent parentEvent
}: { defaultContent?: string; parentEvent?: Event } = {}) { }: { defaultContent?: string; parentEvent?: Event } = {}) {
return ( return (
this.normalPostCache.get(this.generateCacheKey(defaultContent, parentEvent)) ?? defaultContent this.normalPostCache.get(this.generateCacheKey(defaultContent, parentEvent)) ?? {
content: defaultContent,
pictureInfos: [] as { url: string; tags: string[][] }[]
}
) )
} }
setNormalPostCache( setNormalPostCache(
{ defaultContent, parentEvent }: { defaultContent?: string; parentEvent?: Event }, { defaultContent, parentEvent }: { defaultContent?: string; parentEvent?: Event },
content: string content: string,
pictureInfos: { url: string; tags: string[][] }[]
) { ) {
this.normalPostCache.set(this.generateCacheKey(defaultContent, parentEvent), content) this.normalPostCache.set(this.generateCacheKey(defaultContent, parentEvent), {
content,
pictureInfos
})
} }
getPicturePostCache() { getPicturePostCache() {