Add nsfw option to reply form

This commit is contained in:
hzrd149 2025-02-05 14:43:15 -06:00
parent 54f0609499
commit 26b376e381
4 changed files with 41 additions and 13 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add nsfw option to reply form

View File

@ -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();

View File

@ -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();

View File

@ -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 (
<Flex as="form" direction="column" gap="2" pb="4" onSubmit={submit} ref={formRef}>
<MagicTextArea
@ -88,6 +100,13 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin
<InsertImageButton onUploaded={insertText} aria-label="Upload image" />
<InsertGifButton onSelectURL={insertText} aria-label="Add gif" />
<InsertReactionButton onSelect={insertText} aria-label="Add emoji" />
<Button
variant="link"
rightIcon={advanced.isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
onClick={advanced.onToggle}
>
More
</Button>
</ButtonGroup>
<ButtonGroup size="sm" ml="auto">
{onCancel && <Button onClick={onCancel}>Cancel</Button>}
@ -96,6 +115,19 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin
</Button>
</ButtonGroup>
</Flex>
{showAdvanced && (
<Flex direction={{ base: "column", lg: "row" }} gap="4">
<Flex direction="column" gap="2" flex={1}>
<Flex gap="2" direction="column">
<Switch {...register("nsfw")}>NSFW</Switch>
{getValues().nsfw && (
<Input {...register("nsfwReason", { required: true })} placeholder="Reason" isRequired />
)}
</Flex>
</Flex>
</Flex>
)}
{preview && preview.content.length > 0 && (
<Box p="2" borderWidth={1} borderRadius="md" mb="2">
<TrustProvider trust>