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 (
+ : }
+ onClick={advanced.onToggle}
+ >
+ More
+
{onCancel && }
@@ -96,6 +115,19 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin
+
+ {showAdvanced && (
+
+
+
+ NSFW
+ {getValues().nsfw && (
+
+ )}
+
+
+
+ )}
{preview && preview.content.length > 0 && (