mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-24 07:20:17 +02:00
Show content warning for NIP-36 notes
This commit is contained in:
parent
0df1db85ae
commit
285a2dd1c7
5
.changeset/rich-plants-explode.md
Normal file
5
.changeset/rich-plants-explode.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add content warning for NIP-36 notes
|
@ -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">
|
||||
|
42
src/components/sensitive-content-warning.tsx
Normal file
42
src/components/sensitive-content-warning.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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 {
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user