From ccf8c219542dd37435fa19dcf6d4db746a0b616a Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 5 Feb 2025 15:18:58 +0800 Subject: [PATCH] feat: support sending only to current relays --- src/components/NoteStats/LikeButton.tsx | 4 +- src/components/NoteStats/RepostButton.tsx | 2 +- .../PostEditor/NormalPostContent.tsx | 58 ++++++------- .../PostEditor/PicturePostContent.tsx | 53 +++++------- src/components/PostEditor/PostOptions.tsx | 82 +++++++++++++++++++ src/components/PostEditor/types.ts | 4 + src/i18n/en.ts | 4 +- src/i18n/zh.ts | 4 +- src/lib/draft-event.ts | 15 ++++ src/providers/NostrProvider/index.tsx | 27 ++++-- src/services/client.service.ts | 21 ++++- 11 files changed, 199 insertions(+), 75 deletions(-) create mode 100644 src/components/PostEditor/PostOptions.tsx create mode 100644 src/components/PostEditor/types.ts diff --git a/src/components/NoteStats/LikeButton.tsx b/src/components/NoteStats/LikeButton.tsx index 93efde6..0b8798f 100644 --- a/src/components/NoteStats/LikeButton.tsx +++ b/src/components/NoteStats/LikeButton.tsx @@ -6,8 +6,8 @@ import client from '@/services/client.service' import { Heart, Loader } from 'lucide-react' import { Event } from 'nostr-tools' import { useEffect, useMemo, useState } from 'react' -import { formatCount } from './utils' import { useTranslation } from 'react-i18next' +import { formatCount } from './utils' export default function LikeButton({ event, @@ -56,7 +56,7 @@ export default function LikeButton({ const targetRelayList = await client.fetchRelayList(event.pubkey) const reaction = createReactionDraftEvent(event) - await publish(reaction, targetRelayList.read.slice(0, 3)) + await publish(reaction, { additionalRelayUrls: targetRelayList.read.slice(0, 3) }) markNoteAsLiked(event.id) } catch (error) { console.error('like failed', error) diff --git a/src/components/NoteStats/RepostButton.tsx b/src/components/NoteStats/RepostButton.tsx index c74008b..018c8e9 100644 --- a/src/components/NoteStats/RepostButton.tsx +++ b/src/components/NoteStats/RepostButton.tsx @@ -64,7 +64,7 @@ export default function RepostButton({ const targetRelayList = await client.fetchRelayList(event.pubkey) const repost = createRepostDraftEvent(event) - await publish(repost, targetRelayList.read.slice(0, 5)) + await publish(repost, { additionalRelayUrls: targetRelayList.read.slice(0, 5) }) markNoteAsReposted(event.id) } catch (error) { console.error('repost failed', error) diff --git a/src/components/PostEditor/NormalPostContent.tsx b/src/components/PostEditor/NormalPostContent.tsx index b94943d..52ff354 100644 --- a/src/components/PostEditor/NormalPostContent.tsx +++ b/src/components/PostEditor/NormalPostContent.tsx @@ -1,18 +1,18 @@ import { Button } from '@/components/ui/button' -import { Label } from '@/components/ui/label' -import { Switch } from '@/components/ui/switch' -import { StorageKey } from '@/constants' import { useToast } from '@/hooks/use-toast' import { createCommentDraftEvent, createShortTextNoteDraftEvent } from '@/lib/draft-event' +import { useFeed } from '@/providers/FeedProvider.tsx' import { useNostr } from '@/providers/NostrProvider' import client from '@/services/client.service' import { ChevronDown, ImageUp, LoaderCircle } from 'lucide-react' import { Event, kinds } from 'nostr-tools' -import { useEffect, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import TextareaWithMentions from '../TextareaWithMentions.tsx' import Mentions from './Mentions' +import PostOptions from './PostOptions.tsx' import Preview from './Preview' +import { TPostOptions } from './types.ts' import Uploader from './Uploader' export default function NormalPostContent({ @@ -27,18 +27,15 @@ export default function NormalPostContent({ const { t } = useTranslation() const { toast } = useToast() const { publish, checkLogin } = useNostr() + const { relayUrls } = useFeed() const [content, setContent] = useState(defaultContent) const [pictureInfos, setPictureInfos] = useState<{ url: string; tags: string[][] }[]>([]) const [posting, setPosting] = useState(false) const [showMoreOptions, setShowMoreOptions] = useState(false) - const [addClientTag, setAddClientTag] = useState(false) + const [postOptions, setPostOptions] = useState({}) const [uploadingPicture, setUploadingPicture] = useState(false) const canPost = !!content && !posting - useEffect(() => { - setAddClientTag(window.localStorage.getItem(StorageKey.ADD_CLIENT_TAG) === 'true') - }, []) - const post = async (e: React.MouseEvent) => { e.stopPropagation() checkLogin(async () => { @@ -54,14 +51,26 @@ export default function NormalPostContent({ const relayList = await client.fetchRelayList(parentEvent.pubkey) additionalRelayUrls.push(...relayList.read.slice(0, 5)) } + let protectedEvent = false + if (postOptions.sendOnlyToCurrentRelays) { + const relayInfos = await client.fetchRelayInfos(relayUrls) + protectedEvent = relayInfos.every((info) => info?.supported_nips?.includes(70)) + } const draftEvent = parentEvent && parentEvent.kind !== kinds.ShortTextNote - ? await createCommentDraftEvent(content, parentEvent, pictureInfos, { addClientTag }) + ? await createCommentDraftEvent(content, parentEvent, pictureInfos, { + addClientTag: postOptions.addClientTag, + protectedEvent + }) : await createShortTextNoteDraftEvent(content, pictureInfos, { parentEvent, - addClientTag + addClientTag: postOptions.addClientTag, + protectedEvent }) - await publish(draftEvent, additionalRelayUrls) + await publish(draftEvent, { + additionalRelayUrls, + specifiedRelayUrls: postOptions.sendOnlyToCurrentRelays ? relayUrls : undefined + }) setContent('') close() } catch (error) { @@ -92,11 +101,6 @@ export default function NormalPostContent({ }) } - const onAddClientTagChange = (checked: boolean) => { - setAddClientTag(checked) - window.localStorage.setItem(StorageKey.ADD_CLIENT_TAG, checked.toString()) - } - return (
- {showMoreOptions && ( -
-
- - -
-
- {t('Show others this was sent via Jumble')} -
-
- )} +
- {showMoreOptions && ( -
-
- - -
-
- {t('Show others this was sent via Jumble')} -
-
- )} +