Show content warning for NIP-36 notes

This commit is contained in:
hzrd149 2023-05-05 08:09:20 -05:00
parent 0df1db85ae
commit 285a2dd1c7
5 changed files with 98 additions and 12 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add content warning for NIP-36 notes

View File

@ -2,7 +2,12 @@ import React, { useMemo } from "react";
import { Link as RouterLink } from "react-router-dom";
import moment from "moment";
import {
Alert,
AlertDescription,
AlertIcon,
AlertTitle,
Box,
Button,
ButtonGroup,
Card,
CardBody,
@ -13,6 +18,7 @@ import {
Heading,
IconButton,
Link,
Spacer,
} from "@chakra-ui/react";
import { NostrEvent } from "../../types/nostr-event";
import { UserAvatarLink } from "../user-avatar-link";
@ -29,7 +35,7 @@ import { convertTimestampToDate } from "../../helpers/date";
import { useCurrentAccount } from "../../hooks/use-current-account";
import ReactionButton from "./buttons/reaction-button";
import NoteZapButton from "./note-zap-button";
import { ExpandProvider } from "./expanded";
import { ExpandProvider, useExpand } from "./expanded";
import useSubject from "../../hooks/use-subject";
import appSettings from "../../services/app-settings";
import EventVerificationIcon from "../event-verification-icon";
@ -38,6 +44,31 @@ import { RepostButton } from "./buttons/repost-button";
import { QuoteRepostButton } from "./buttons/quote-repost-button";
import { useReadRelayUrls } from "../../hooks/use-client-relays";
import { ExternalLinkIcon } from "../icons";
import SensitiveContentWarning from "../sensitive-content-warning";
import useAppSettings from "../../hooks/use-app-settings";
function NoteContentWithWarning({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
const account = useCurrentAccount();
const expand = useExpand();
const settings = useAppSettings();
const readRelays = useReadRelayUrls();
const contacts = useUserContacts(account.pubkey, readRelays);
const following = contacts?.contacts || [];
const contentWarning = event.tags.find((t) => t[0] === "content-warning")?.[1];
const showContentWarning = settings.showContentWarning && contentWarning && !expand?.expanded;
return showContentWarning ? (
<SensitiveContentWarning description={contentWarning} />
) : (
<NoteContents
event={event}
trusted={event.pubkey === account.pubkey || following.includes(event.pubkey)}
maxHeight={maxHeight}
/>
);
}
export type NoteProps = {
event: NostrEvent;
@ -46,13 +77,8 @@ export type NoteProps = {
};
export const Note = React.memo(({ event, maxHeight, variant = "outline" }: NoteProps) => {
const isMobile = useIsMobile();
const account = useCurrentAccount();
const { showReactions, showSignatureVerification } = useSubject(appSettings);
const readRelays = useReadRelayUrls();
const contacts = useUserContacts(account.pubkey, readRelays);
const following = contacts?.contacts || [];
// find mostr external link
const externalLink = useMemo(() => event.tags.find((t) => t[0] === "mostr"), [event]);
@ -75,11 +101,7 @@ export const Note = React.memo(({ event, maxHeight, variant = "outline" }: NoteP
</Flex>
</CardHeader>
<CardBody px="2" py="0">
<NoteContents
event={event}
trusted={event.pubkey === account.pubkey || following.includes(event.pubkey)}
maxHeight={maxHeight}
/>
<NoteContentWithWarning event={event} maxHeight={maxHeight} />
</CardBody>
<CardFooter padding="2" display="flex" gap="2">
<ButtonGroup size="sm" variant="link">

View File

@ -0,0 +1,42 @@
import { Alert, AlertDescription, AlertIcon, AlertProps, AlertTitle, Button, Spacer, useModal } from "@chakra-ui/react";
import { useIsMobile } from "../hooks/use-is-mobile";
import { useExpand } from "./note/expanded";
export default function SensitiveContentWarning({ description }: { description: string } & AlertProps) {
const isMobile = useIsMobile();
const expand = useExpand();
if (isMobile) {
return (
<Alert
status="warning"
flexDirection="column"
alignItems="center"
justifyContent="center"
textAlign="center"
height="200px"
>
<AlertIcon boxSize="40px" mr={0} />
<AlertTitle mt={4} mb={1} fontSize="lg">
Sensitive Content
</AlertTitle>
<AlertDescription maxWidth="sm">{description}</AlertDescription>
<Button mt="2" onClick={expand?.onExpand} colorScheme="red">
Show
</Button>
</Alert>
);
}
return (
<Alert status="warning">
<AlertIcon boxSize="30px" mr="4" />
<AlertTitle fontSize="lg">Sensitive Content</AlertTitle>
<AlertDescription maxWidth="sm">{description}</AlertDescription>
<Spacer />
<Button mt="2" onClick={expand?.onExpand} colorScheme="red">
Show
</Button>
</Alert>
);
}

View File

@ -26,6 +26,7 @@ export type AppSettings = {
zapAmounts: number[];
primaryColor: string;
imageProxy: string;
showContentWarning: boolean;
};
export const defaultSettings: AppSettings = {
@ -39,6 +40,7 @@ export const defaultSettings: AppSettings = {
zapAmounts: [50, 200, 500, 1000],
primaryColor: "#8DB600",
imageProxy: "",
showContentWarning: true,
};
function parseAppSettings(event: NostrEvent): AppSettings {

View File

@ -44,7 +44,7 @@ function ColorPicker({ value, onPickColor, ...props }: { onPickColor?: (color: s
}
export default function DisplaySettings() {
const { blurImages, colorMode, primaryColor, updateSettings } = useAppSettings();
const { blurImages, colorMode, primaryColor, updateSettings, showContentWarning } = useAppSettings();
return (
<AccordionItem>
@ -106,6 +106,21 @@ export default function DisplaySettings() {
<span>Enabled: blur images for people you aren't following</span>
</FormHelperText>
</FormControl>
<FormControl>
<Flex alignItems="center">
<FormLabel htmlFor="show-content-warning" mb="0">
Show content warning
</FormLabel>
<Switch
id="show-content-warning"
isChecked={showContentWarning}
onChange={(v) => updateSettings({ showContentWarning: v.target.checked })}
/>
</Flex>
<FormHelperText>
<span>Enabled: shows a warning for notes with NIP-36 Content Warning</span>
</FormHelperText>
</FormControl>
<FormControl>
<Flex alignItems="center">
<FormLabel htmlFor="show-ads" mb="0">