add option to hide media

This commit is contained in:
hzrd149
2023-02-07 17:04:19 -06:00
parent 88ae0aad36
commit f1dda73d54
6 changed files with 68 additions and 10 deletions

View File

@@ -62,6 +62,8 @@
- make app handle image files
- block notes based on content
- implement NIP-56 and blocking
- allow user to select relay or following list when fetching replies (default to my relays + following?)
- filter list of followers by users the user has blocked/reported (stops bots/spammers from showing up at followers)
## Setup

View File

@@ -109,3 +109,9 @@ export const RelayIcon = createIcon({
d: "M11 14v-3h2v3h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h5zM2.51 8.837C3.835 4.864 7.584 2 12 2s8.166 2.864 9.49 6.837l-1.898.632a8.003 8.003 0 0 0-15.184 0l-1.897-.632zm3.796 1.265a6.003 6.003 0 0 1 11.388 0l-1.898.633a4.002 4.002 0 0 0-7.592 0l-1.898-.633z",
defaultProps,
});
export const ExternalLinkIcon = createIcon({
displayName: "eternal-link-icon",
d: "M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z",
defaultProps,
});

View File

@@ -1,5 +1,15 @@
import React from "react";
import { AspectRatio, Box, Image, ImageProps, Link, PinInputField, useDisclosure } from "@chakra-ui/react";
import React, { useState } from "react";
import {
AspectRatio,
Box,
Button,
ButtonGroup,
IconButton,
Image,
ImageProps,
Link,
useDisclosure,
} from "@chakra-ui/react";
import { InlineInvoiceCard } from "../inline-invoice-card";
import { TweetEmbed } from "../tweet-embed";
import { UserLink } from "../user-link";
@@ -7,6 +17,7 @@ import { normalizeToHex } from "../../helpers/nip-19";
import { NostrEvent } from "../../types/nostr-event";
import { NoteLink } from "../note-link";
import settings from "../../services/settings";
// import { ExternalLinkIcon } from "../icons";
const BlurredImage = (props: ImageProps) => {
const { isOpen, onToggle } = useDisclosure();
@@ -16,16 +27,19 @@ const BlurredImage = (props: ImageProps) => {
const embeds: {
regexp: RegExp;
render: (match: RegExpMatchArray, event?: NostrEvent, trusted?: boolean) => JSX.Element | string;
isMedia: boolean;
}[] = [
// Lightning Invoice
{
regexp: /(lightning:)?(LNBC[A-Za-z0-9]+)/im,
render: (match) => <InlineInvoiceCard paymentRequest={match[2]} />,
isMedia: false,
},
// Twitter tweet
{
regexp: /^https?:\/\/twitter\.com\/(?:\#!\/)?(\w+)\/status(es)?\/(\d+)[^\s]+/im,
render: (match) => <TweetEmbed href={match[0]} conversation={false} />,
isMedia: true,
},
// Youtube Video
{
@@ -43,6 +57,7 @@ const embeds: {
></iframe>
</AspectRatio>
),
isMedia: true,
},
// Youtube Music
{
@@ -58,6 +73,7 @@ const embeds: {
></iframe>
</AspectRatio>
),
isMedia: true,
},
// Tidal
{
@@ -69,6 +85,7 @@ const embeds: {
height="96"
></iframe>
),
isMedia: true,
},
// Spotify
{
@@ -86,6 +103,7 @@ const embeds: {
src={`https://open.spotify.com/embed/${match[1]}/${match[2]}`}
></iframe>
),
isMedia: true,
},
// apple music
{
@@ -100,6 +118,7 @@ const embeds: {
src={match[0].replace("music.apple.com", "embed.music.apple.com")}
></iframe>
),
isMedia: true,
},
// Image
{
@@ -108,6 +127,7 @@ const embeds: {
const ImageComponent = trusted || !settings.blurImages.value ? Image : BlurredImage;
return <ImageComponent src={match[0]} width="100%" maxWidth="30rem" />;
},
isMedia: true,
},
// Video
{
@@ -117,6 +137,7 @@ const embeds: {
<video src={match[0]} controls />
</AspectRatio>
),
isMedia: true,
},
// Link
{
@@ -126,6 +147,7 @@ const embeds: {
{match[0]}
</Link>
),
isMedia: false,
},
// npub1 and note1 links
{
@@ -139,6 +161,7 @@ const embeds: {
return match[0];
}
},
isMedia: false,
},
// Nostr Mention Links
{
@@ -158,26 +181,41 @@ const embeds: {
return match[0];
},
isMedia: false,
},
// bold text
{
regexp: /\*\*([^\n]+)\*\*/im,
render: (match) => <span style={{ fontWeight: "bold" }}>{match[1]}</span>,
isMedia: false,
},
];
const MediaEmbed = ({ children }: { children: JSX.Element | string }) => {
const [show, setShow] = useState(settings.autoShowMedia.value);
return show ? (
<>{children}</>
) : (
<ButtonGroup size="sm" isAttached variant="outline">
<Button onClick={() => setShow(true)}>Show Embed</Button>
{/* TODO: add external link for embed */}
{/* <IconButton as="a" aria-label="Add to friends" icon={<ExternalLinkIcon />} href={}/> */}
</ButtonGroup>
);
};
function embedContent(content: string, event?: NostrEvent, trusted: boolean = false): (string | JSX.Element)[] {
for (const { regexp, render } of embeds) {
const match = content.match(regexp);
for (const embedType of embeds) {
const match = content.match(embedType.regexp);
if (match && match.index !== undefined) {
const before = content.slice(0, match.index);
const after = content.slice(match.index + match[0].length, content.length);
return [
...embedContent(before, event, trusted),
render(match, event, trusted),
...embedContent(after, event, trusted),
];
const embedRender = embedType.render(match, event, trusted);
const embed = embedType.isMedia ? <MediaEmbed>{embedRender}</MediaEmbed> : embedRender;
return [...embedContent(before, event, trusted), embed, ...embedContent(after, event, trusted)];
}
}
return [content];

View File

@@ -4,7 +4,7 @@ import { truncatedId } from "./nostr-event";
export function getUserDisplayName(metadata: Kind0ParsedContent | undefined, pubkey: string) {
if (metadata?.display_name && metadata?.name) {
return `${metadata.display_name} (${metadata.name})`;
return metadata.display_name;
} else if (metadata?.name) {
return metadata.name;
}

View File

@@ -6,6 +6,7 @@ const settings = {
relays: new BehaviorSubject<string[]>([]),
identity: new BehaviorSubject<SavedIdentity | null>(null),
blurImages: new BehaviorSubject(true),
autoShowMedia: new BehaviorSubject(true),
};
async function loadSettings() {

View File

@@ -34,6 +34,7 @@ export const SettingsView = () => {
const navigate = useNavigate();
const relays = useSubject(settings.relays);
const blurImages = useSubject(settings.blurImages);
const autoShowMedia = useSubject(settings.autoShowMedia);
const [relayInputValue, setRelayInputValue] = useState("");
const { colorMode, setColorMode } = useColorMode();
@@ -155,6 +156,16 @@ export const SettingsView = () => {
onChange={(v) => settings.blurImages.next(v.target.checked)}
/>
</FormControl>
<FormControl display="flex" alignItems="center">
<FormLabel htmlFor="auto-show-embeds" mb="0">
Automatically show media
</FormLabel>
<Switch
id="auto-show-embeds"
isChecked={autoShowMedia}
onChange={(v) => settings.autoShowMedia.next(v.target.checked)}
/>
</FormControl>
<FormControl display="flex" alignItems="center">
<FormLabel htmlFor="show-ads" mb="0">
Show Ads