diff --git a/src/components/note/expanded.tsx b/src/components/note/expanded.tsx new file mode 100644 index 000000000..d28e56171 --- /dev/null +++ b/src/components/note/expanded.tsx @@ -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(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 ( + {children} + ); +} diff --git a/src/components/note/index.tsx b/src/components/note/index.tsx index fcfcdf3e6..2059061ad 100644 --- a/src/components/note/index.tsx +++ b/src/components/note/index.tsx @@ -32,6 +32,7 @@ import { convertTimestampToDate } from "../../helpers/date"; import { useCurrentAccount } from "../../hooks/use-current-account"; import NoteLikeButton from "./note-like-button"; import NoteZapButton from "./note-zap-button"; +import { ExpandProvider } from "./expanded"; export type NoteProps = { event: NostrEvent; @@ -49,51 +50,53 @@ export const Note = React.memo(({ event, maxHeight }: NoteProps) => { const share = () => openModal(buildShare(event)); return ( - - - - + + + + + - - - - - {!isMobile && } - - {moment(convertTimestampToDate(event.created_at)).fromNow()} - - - - - - - - } - title="Reply" - aria-label="Reply" - onClick={reply} - size="sm" - isDisabled={account.readonly} - /> - } - onClick={share} - aria-label="Share Note" - title="Share Note" - size="sm" - isDisabled={account.readonly} - /> - - - - - - - - - + + + + + {!isMobile && } + + {moment(convertTimestampToDate(event.created_at)).fromNow()} + + + + + + + + } + title="Reply" + aria-label="Reply" + onClick={reply} + size="sm" + isDisabled={account.readonly} + /> + } + onClick={share} + aria-label="Share Note" + title="Share Note" + size="sm" + isDisabled={account.readonly} + /> + + + + + + + + + + ); }); diff --git a/src/components/note/note-contents.tsx b/src/components/note/note-contents.tsx index 56a333dfb..dba3f9060 100644 --- a/src/components/note/note-contents.tsx +++ b/src/components/note/note-contents.tsx @@ -1,25 +1,14 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; -import { - AspectRatio, - Box, - Button, - ButtonGroup, - IconButton, - Image, - ImageProps, - Link, - useDisclosure, -} from "@chakra-ui/react"; +import { AspectRatio, Box, Button, ButtonGroup, Image, ImageProps, Link, useDisclosure } from "@chakra-ui/react"; import { InlineInvoiceCard } from "../inline-invoice-card"; import { TweetEmbed } from "../tweet-embed"; import { UserLink } from "../user-link"; import { normalizeToHex } from "../../helpers/nip19"; import { DraftNostrEvent, NostrEvent } from "../../types/nostr-event"; -import { NoteLink } from "../note-link"; import settings from "../../services/settings"; import styled from "@emotion/styled"; import QuoteNote from "./quote-note"; -// import { ExternalLinkIcon } from "../icons"; +import { useExpand } from "./expanded"; const BlurredImage = (props: ImageProps) => { const { isOpen, onToggle } = useDisclosure(); @@ -299,33 +288,37 @@ export type NoteContentsProps = { export const NoteContents = React.memo(({ event, trusted, maxHeight }: NoteContentsProps) => { const parts = embedContent(event.content, event, trusted ?? false); - const [height, setHeight] = useState(maxHeight); + const expand = useExpand(); + const [innerHeight, setInnerHeight] = useState(0); const ref = useRef(null); const testHeight = useCallback(() => { if (ref.current && maxHeight) { const rect = ref.current.getClientRects()[0]; - setHeight(rect.height < maxHeight ? undefined : maxHeight); + setInnerHeight(rect.height); } - }, [maxHeight, setHeight]); + }, [maxHeight]); useEffect(() => { testHeight(); }, [testHeight]); + const showOverlay = !!maxHeight && !expand?.expanded && innerHeight > maxHeight; + return ( testHeight()} > - {parts.map((part, i) => ( - {part} - ))} - {height && setHeight(undefined)} />} +
+ {parts.map((part, i) => ( + {part} + ))} +
+ {showOverlay && }
); }); diff --git a/src/components/zap-modal.tsx b/src/components/zap-modal.tsx index a6850b6fe..fc48a1288 100644 --- a/src/components/zap-modal.tsx +++ b/src/components/zap-modal.tsx @@ -78,6 +78,7 @@ export default function ZapModal({ const onSubmitZap: SubmitHandler = async (values) => { try { + if (!tipAddress) throw new Error("No lightning address"); if (lnurlMetadata) { const amountInMilisat = values.amount * 1000; @@ -123,7 +124,7 @@ export default function ZapModal({ setInvoice(payRequest); } 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) { 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 ( - +