diff --git a/.changeset/rude-carrots-juggle.md b/.changeset/rude-carrots-juggle.md new file mode 100644 index 000000000..2b14b9f84 --- /dev/null +++ b/.changeset/rude-carrots-juggle.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Add nsfw option to reply form diff --git a/src/views/settings/cache/components/nostr-relay-tray-card.tsx b/src/views/settings/cache/components/nostr-relay-tray-card.tsx index 0c5e1de2a..c83aa2191 100644 --- a/src/views/settings/cache/components/nostr-relay-tray-card.tsx +++ b/src/views/settings/cache/components/nostr-relay-tray-card.tsx @@ -1,9 +1,9 @@ +import { useState } from "react"; import { useAsync } from "react-use"; import { Button, Card, CardBody, CardHeader, Heading, Link, Text } from "@chakra-ui/react"; import { NOSTR_RELAY_TRAY_URL, checkNostrRelayTray, setCacheRelayURL } from "../../../../services/cache-relay"; import useCacheRelay from "../../../../hooks/use-cache-relay"; -import { useState } from "react"; export default function NostrRelayTrayCard() { const cacheRelay = useCacheRelay(); diff --git a/src/views/settings/media-servers/index.tsx b/src/views/settings/media-servers/index.tsx index 2d9dbb667..156edc0b2 100644 --- a/src/views/settings/media-servers/index.tsx +++ b/src/views/settings/media-servers/index.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { Alert, AlertDescription, @@ -12,13 +11,6 @@ import { IconButton, Input, Link, - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, Text, useToast, } from "@chakra-ui/react"; @@ -37,7 +29,6 @@ import useAsyncErrorHandler from "../../../hooks/use-async-error-handler"; import { isServerTag } from "../../../helpers/nostr/blossom"; import { USER_BLOSSOM_SERVER_LIST_KIND, areServersEqual } from "blossom-client-sdk"; import SimpleView from "../../../components/layout/presets/simple-view"; -import OpenGraphCard from "../../../components/open-graph/open-graph-card"; function MediaServersPage() { const toast = useToast(); diff --git a/src/views/thread/components/reply-form.tsx b/src/views/thread/components/reply-form.tsx index 35f29382b..7a036a40d 100644 --- a/src/views/thread/components/reply-form.tsx +++ b/src/views/thread/components/reply-form.tsx @@ -1,5 +1,5 @@ import { useMemo, useRef } from "react"; -import { Box, Button, ButtonGroup, Flex } from "@chakra-ui/react"; +import { Box, Button, ButtonGroup, Flex, Input, Switch, useDisclosure } from "@chakra-ui/react"; import { useForm } from "react-hook-form"; import { useAsync, useThrottle } from "react-use"; import { kinds } from "nostr-tools"; @@ -18,6 +18,7 @@ import useTextAreaUploadFile, { useTextAreaInsertTextWithForm } from "../../../h import InsertGifButton from "../../../components/gif/insert-gif-button"; import InsertImageButton from "../../new/note/insert-image-button"; import InsertReactionButton from "../../../components/reactions/insert-reaction-button"; +import { ChevronDownIcon, ChevronUpIcon } from "../../../components/icons"; export type ReplyFormProps = { item: ThreadItem; @@ -30,16 +31,24 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin const publish = usePublishEvent(); const factory = useEventFactory(); const emojis = useContextEmojis(); + const advanced = useDisclosure(); const customEmojis = useMemo(() => emojis.filter((e) => !!e.url) as Emoji[], [emojis]); - const { setValue, getValues, watch, handleSubmit, formState, reset } = useForm({ + const { setValue, getValues, watch, handleSubmit, formState, reset, register } = useForm({ defaultValues: { content: "", + nsfw: false, + nsfwReason: "", }, mode: "all", }); - const clearCache = useCacheForm<{ content: string }>(`reply-${item.event.id}`, getValues, reset, formState); + const clearCache = useCacheForm<{ content: string; nsfw: boolean; nsfwReason: string }>( + `reply-${item.event.id}`, + getValues, + reset, + formState, + ); watch("content"); @@ -50,6 +59,7 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin const submit = handleSubmit(async (values) => { const draft = await factory.noteReply(item.event, values.content, { emojis: customEmojis, + contentWarning: values.nsfw ? values.nsfwReason || values.nsfw : false, }); const pub = await publish("Reply", draft); @@ -67,6 +77,8 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin [throttleValues, customEmojis], ); + const showAdvanced = advanced.isOpen || formState.dirtyFields.nsfw; + return ( + {onCancel && } @@ -96,6 +115,19 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin + + {showAdvanced && ( + + + + NSFW + {getValues().nsfw && ( + + )} + + + + )} {preview && preview.content.length > 0 && (