add share option to event console

This commit is contained in:
hzrd149 2024-03-18 15:53:32 -05:00
parent 44ac1e8631
commit 8dbf7c3405
3 changed files with 50 additions and 25 deletions

View File

@ -3,19 +3,26 @@ import { IconButton, IconButtonProps, useToast } from "@chakra-ui/react";
import { CheckIcon, CopyToClipboardIcon } from "./icons";
export const CopyIconButton = ({ value, ...props }: { value?: string } & Omit<IconButtonProps, "icon">) => {
type CopyIconButtonProps = Omit<IconButtonProps, "icon" | "value"> & {
value: string | undefined | (() => string);
icon?: IconButtonProps["icon"];
};
export const CopyIconButton = ({ value, icon, ...props }: CopyIconButtonProps) => {
const toast = useToast();
const [copied, setCopied] = useState(false);
return (
<IconButton
icon={copied ? <CheckIcon /> : <CopyToClipboardIcon />}
icon={copied ? <CheckIcon /> : icon || <CopyToClipboardIcon />}
onClick={() => {
if (value && navigator.clipboard && !copied) {
navigator.clipboard.writeText(value);
const v: string | undefined = typeof value === "function" ? value() : value;
if (v && navigator.clipboard && !copied) {
navigator.clipboard.writeText(v);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} else toast({ description: value, isClosable: true, duration: null });
} else toast({ description: v, isClosable: true, duration: null });
}}
{...props}
/>

View File

@ -1,17 +1,5 @@
import { useContext } from "react";
import {
Box,
Card,
CardBody,
CardProps,
Flex,
Heading,
Image,
LinkBox,
LinkOverlay,
Tag,
Text,
} from "@chakra-ui/react";
import { Box, Card, CardBody, CardProps, Flex, Heading, Image, LinkBox, Tag, Text, useToast } from "@chakra-ui/react";
import {
getArticleImage,
@ -27,15 +15,21 @@ import Timestamp from "../../timestamp";
import { AppHandlerContext } from "../../../providers/route/app-handler-provider";
export default function EmbeddedArticle({ article, ...props }: Omit<CardProps, "children"> & { article: NostrEvent }) {
const toast = useToast();
const title = getArticleTitle(article);
const image = getArticleImage(article);
const summary = getArticleSummary(article);
const naddr = getSharableEventAddress(article);
const { openAddress } = useContext(AppHandlerContext);
const open = () => {
const naddr = getSharableEventAddress(article);
if (naddr) openAddress(naddr);
else toast({ status: "error", description: "Failed to get address" });
};
return (
<Card as={LinkBox} size="sm" onClick={() => naddr && openAddress(naddr)} cursor="pointer" {...props}>
<Card as={LinkBox} size="sm" onClick={open} cursor="pointer" {...props}>
{image && (
<Box
backgroundImage={image}

View File

@ -19,6 +19,8 @@ import { NostrEvent, Relay, Subscription } from "nostr-tools";
import { useLocalStorage } from "react-use";
import { Subscription as IDBSubscription, CacheRelay } from "nostr-idb";
import _throttle from "lodash.throttle";
import stringify from "json-stringify-deterministic";
import { useSearchParams } from "react-router-dom";
import VerticalPageLayout from "../../../components/vertical-page-layout";
import BackButton from "../../../components/router/back-button";
@ -30,11 +32,12 @@ import EventRow from "./event-row";
import { processFilter } from "./process";
import HelpModal from "./help-modal";
import HelpCircle from "../../../components/icons/help-circle";
import stringify from "json-stringify-deterministic";
import { DownloadIcon } from "../../../components/icons";
import { DownloadIcon, ShareIcon } from "../../../components/icons";
import { RelayUrlInput } from "../../../components/relay-url-input";
import { validateRelayURL } from "../../../helpers/relay";
import FilterEditor from "./filter-editor";
import { CopyIconButton } from "../../../components/copy-icon-button";
import { safeJson } from "../../../helpers/parse";
const EventTimeline = memo(({ events }: { events: NostrEvent[] }) => {
return (
@ -47,16 +50,27 @@ const EventTimeline = memo(({ events }: { events: NostrEvent[] }) => {
});
export default function EventConsoleView() {
const [params, setParams] = useSearchParams();
const historyDrawer = useDisclosure();
const [history, setHistory] = useLocalStorage<string[]>("console-history", []);
const helpModal = useDisclosure();
const queryRelay = useDisclosure();
const [relayURL, setRelayURL] = useState("");
const queryRelay = useDisclosure({ defaultIsOpen: params.has("relay") });
const [relayURL, setRelayURL] = useState(params.get("relay") || "");
const [relay, setRelay] = useState<Relay | null>(null);
const [sub, setSub] = useState<Subscription | IDBSubscription | null>(null);
const [query, setQuery] = useState(() => history?.[0] || JSON.stringify({ kinds: [1], limit: 20 }, null, 2));
const [query, setQuery] = useState(() => {
if (params.has("filter")) {
const str = params.get("filter");
if (str) {
const f = safeJson(str, null);
if (f) return JSON.stringify(f, null, 2);
}
}
if (history?.[0]) return history?.[0];
return JSON.stringify({ kinds: [1], limit: 20 }, null, 2);
});
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
@ -122,6 +136,13 @@ export default function EventConsoleView() {
window.open(url, "_blank");
};
const updateSharedURL = () => {
const p = new URLSearchParams(params);
p.set("filter", query);
p.set("relay", relayURL);
setParams(p, { replace: true });
};
return (
<VerticalPageLayout>
<Flex gap="2" alignItems="center" wrap="wrap">
@ -141,6 +162,9 @@ export default function EventConsoleView() {
)}
<ButtonGroup ml="auto">
<IconButton icon={<HelpCircle />} aria-label="Help" title="Help" size="sm" onClick={helpModal.onOpen} />
{queryRelay.isOpen && (
<IconButton icon={<ShareIcon />} aria-label="Share" size="sm" onClick={updateSharedURL} />
)}
<IconButton
icon={<ClockRewind />}
aria-label="History"