mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-01 00:19:45 +02:00
add share option to event console
This commit is contained in:
parent
44ac1e8631
commit
8dbf7c3405
@ -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}
|
||||
/>
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user