fix embeded note expanding

This commit is contained in:
hzrd149
2023-03-04 16:22:10 -06:00
parent 4b0d8a4073
commit 4bd04eb644
4 changed files with 94 additions and 70 deletions

View File

@@ -0,0 +1,19 @@
import { useDisclosure } from "@chakra-ui/react";
import React, { PropsWithChildren, useContext, useMemo } from "react";
type ContextType = { expanded: boolean; onExpand: () => void; onCollapse: () => void; onToggle: () => void };
const ExpandedContext = React.createContext<ContextType | undefined>(undefined);
export function useExpand() {
const ctx = useContext(ExpandedContext);
return ctx;
}
export function ExpandProvider({ children }: PropsWithChildren) {
const { isOpen: expanded, onOpen: onExpand, onClose: onCollapse, onToggle } = useDisclosure();
return (
<ExpandedContext.Provider value={{ expanded, onExpand, onCollapse, onToggle }}>{children}</ExpandedContext.Provider>
);
}

View File

@@ -32,6 +32,7 @@ import { convertTimestampToDate } from "../../helpers/date";
import { useCurrentAccount } from "../../hooks/use-current-account"; import { useCurrentAccount } from "../../hooks/use-current-account";
import NoteLikeButton from "./note-like-button"; import NoteLikeButton from "./note-like-button";
import NoteZapButton from "./note-zap-button"; import NoteZapButton from "./note-zap-button";
import { ExpandProvider } from "./expanded";
export type NoteProps = { export type NoteProps = {
event: NostrEvent; event: NostrEvent;
@@ -49,6 +50,7 @@ export const Note = React.memo(({ event, maxHeight }: NoteProps) => {
const share = () => openModal(buildShare(event)); const share = () => openModal(buildShare(event));
return ( return (
<ExpandProvider>
<Card variant="outline"> <Card variant="outline">
<CardHeader padding="2"> <CardHeader padding="2">
<Flex flex="1" gap="2" alignItems="center" wrap="wrap"> <Flex flex="1" gap="2" alignItems="center" wrap="wrap">
@@ -95,5 +97,6 @@ export const Note = React.memo(({ event, maxHeight }: NoteProps) => {
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" /> <NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
</CardFooter> </CardFooter>
</Card> </Card>
</ExpandProvider>
); );
}); });

View File

@@ -1,25 +1,14 @@
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import { import { AspectRatio, Box, Button, ButtonGroup, Image, ImageProps, Link, useDisclosure } from "@chakra-ui/react";
AspectRatio,
Box,
Button,
ButtonGroup,
IconButton,
Image,
ImageProps,
Link,
useDisclosure,
} from "@chakra-ui/react";
import { InlineInvoiceCard } from "../inline-invoice-card"; import { InlineInvoiceCard } from "../inline-invoice-card";
import { TweetEmbed } from "../tweet-embed"; import { TweetEmbed } from "../tweet-embed";
import { UserLink } from "../user-link"; import { UserLink } from "../user-link";
import { normalizeToHex } from "../../helpers/nip19"; import { normalizeToHex } from "../../helpers/nip19";
import { DraftNostrEvent, NostrEvent } from "../../types/nostr-event"; import { DraftNostrEvent, NostrEvent } from "../../types/nostr-event";
import { NoteLink } from "../note-link";
import settings from "../../services/settings"; import settings from "../../services/settings";
import styled from "@emotion/styled"; import styled from "@emotion/styled";
import QuoteNote from "./quote-note"; import QuoteNote from "./quote-note";
// import { ExternalLinkIcon } from "../icons"; import { useExpand } from "./expanded";
const BlurredImage = (props: ImageProps) => { const BlurredImage = (props: ImageProps) => {
const { isOpen, onToggle } = useDisclosure(); const { isOpen, onToggle } = useDisclosure();
@@ -299,33 +288,37 @@ export type NoteContentsProps = {
export const NoteContents = React.memo(({ event, trusted, maxHeight }: NoteContentsProps) => { export const NoteContents = React.memo(({ event, trusted, maxHeight }: NoteContentsProps) => {
const parts = embedContent(event.content, event, trusted ?? false); const parts = embedContent(event.content, event, trusted ?? false);
const [height, setHeight] = useState(maxHeight); const expand = useExpand();
const [innerHeight, setInnerHeight] = useState(0);
const ref = useRef<HTMLDivElement | null>(null); const ref = useRef<HTMLDivElement | null>(null);
const testHeight = useCallback(() => { const testHeight = useCallback(() => {
if (ref.current && maxHeight) { if (ref.current && maxHeight) {
const rect = ref.current.getClientRects()[0]; const rect = ref.current.getClientRects()[0];
setHeight(rect.height < maxHeight ? undefined : maxHeight); setInnerHeight(rect.height);
} }
}, [maxHeight, setHeight]); }, [maxHeight]);
useEffect(() => { useEffect(() => {
testHeight(); testHeight();
}, [testHeight]); }, [testHeight]);
const showOverlay = !!maxHeight && !expand?.expanded && innerHeight > maxHeight;
return ( return (
<Box <Box
ref={ref}
whiteSpace="pre-wrap" whiteSpace="pre-wrap"
maxHeight={height} maxHeight={!expand?.expanded ? maxHeight : undefined}
position="relative" position="relative"
overflow={maxHeight ? "hidden" : "initial"} overflow={maxHeight && !expand?.expanded ? "hidden" : "initial"}
onLoad={() => testHeight()} onLoad={() => testHeight()}
> >
<div ref={ref}>
{parts.map((part, i) => ( {parts.map((part, i) => (
<span key={"part-" + i}>{part}</span> <span key={"part-" + i}>{part}</span>
))} ))}
{height && <GradientOverlay onClick={() => setHeight(undefined)} />} </div>
{showOverlay && <GradientOverlay onClick={expand?.onExpand} />}
</Box> </Box>
); );
}); });

View File

@@ -78,6 +78,7 @@ export default function ZapModal({
const onSubmitZap: SubmitHandler<FormValues> = async (values) => { const onSubmitZap: SubmitHandler<FormValues> = async (values) => {
try { try {
if (!tipAddress) throw new Error("No lightning address");
if (lnurlMetadata) { if (lnurlMetadata) {
const amountInMilisat = values.amount * 1000; const amountInMilisat = values.amount * 1000;
@@ -123,7 +124,7 @@ export default function ZapModal({
setInvoice(payRequest); setInvoice(payRequest);
} else throw new Error("Failed to get invoice"); } else throw new Error("Failed to get invoice");
} }
} else throw new Error("No lightning address"); } else throw new Error("Failed to get LNURL metadata");
} catch (e) { } catch (e) {
if (e instanceof Error) toast({ status: "error", description: e.message }); if (e instanceof Error) toast({ status: "error", description: e.message });
} }
@@ -157,8 +158,16 @@ export default function ZapModal({
); );
}; };
const handleClose = () => {
// if there was an invoice and we a closing the modal. presume it was paid
if (invoice && onPaid) {
onPaid();
}
onClose();
};
return ( return (
<Modal onClose={onClose} {...props}> <Modal onClose={handleClose} {...props}>
<ModalOverlay /> <ModalOverlay />
<ModalContent> <ModalContent>
<ModalBody padding="4"> <ModalBody padding="4">