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 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 (
<Card variant="outline">
<CardHeader padding="2">
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
<UserAvatarLink pubkey={event.pubkey} size={isMobile ? "xs" : "sm"} />
<ExpandProvider>
<Card variant="outline">
<CardHeader padding="2">
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
<UserAvatarLink pubkey={event.pubkey} size={isMobile ? "xs" : "sm"} />
<Heading size="sm" display="inline">
<UserLink pubkey={event.pubkey} />
</Heading>
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
{!isMobile && <Flex grow={1} />}
<Link as={RouterLink} to={`/n/${normalizeToBech32(event.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
{moment(convertTimestampToDate(event.created_at)).fromNow()}
</Link>
</Flex>
</CardHeader>
<CardBody px="2" py="0">
<NoteContents event={event} trusted={following.includes(event.pubkey)} maxHeight={maxHeight} />
</CardBody>
<CardFooter padding="2" display="flex" gap="2">
<IconButton
variant="link"
icon={<ReplyIcon />}
title="Reply"
aria-label="Reply"
onClick={reply}
size="sm"
isDisabled={account.readonly}
/>
<IconButton
variant="link"
icon={<ShareIcon />}
onClick={share}
aria-label="Share Note"
title="Share Note"
size="sm"
isDisabled={account.readonly}
/>
<ButtonGroup size="sm" variant="link">
<NoteZapButton note={event} size="sm" />
<NoteLikeButton note={event} size="sm" />
</ButtonGroup>
<Box flexGrow={1} />
<NoteRelays event={event} size="sm" variant="link" />
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
</CardFooter>
</Card>
<Heading size="sm" display="inline">
<UserLink pubkey={event.pubkey} />
</Heading>
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
{!isMobile && <Flex grow={1} />}
<Link as={RouterLink} to={`/n/${normalizeToBech32(event.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
{moment(convertTimestampToDate(event.created_at)).fromNow()}
</Link>
</Flex>
</CardHeader>
<CardBody px="2" py="0">
<NoteContents event={event} trusted={following.includes(event.pubkey)} maxHeight={maxHeight} />
</CardBody>
<CardFooter padding="2" display="flex" gap="2">
<IconButton
variant="link"
icon={<ReplyIcon />}
title="Reply"
aria-label="Reply"
onClick={reply}
size="sm"
isDisabled={account.readonly}
/>
<IconButton
variant="link"
icon={<ShareIcon />}
onClick={share}
aria-label="Share Note"
title="Share Note"
size="sm"
isDisabled={account.readonly}
/>
<ButtonGroup size="sm" variant="link">
<NoteZapButton note={event} size="sm" />
<NoteLikeButton note={event} size="sm" />
</ButtonGroup>
<Box flexGrow={1} />
<NoteRelays event={event} size="sm" variant="link" />
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
</CardFooter>
</Card>
</ExpandProvider>
);
});

View File

@@ -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<HTMLDivElement | null>(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 (
<Box
ref={ref}
whiteSpace="pre-wrap"
maxHeight={height}
maxHeight={!expand?.expanded ? maxHeight : undefined}
position="relative"
overflow={maxHeight ? "hidden" : "initial"}
overflow={maxHeight && !expand?.expanded ? "hidden" : "initial"}
onLoad={() => testHeight()}
>
{parts.map((part, i) => (
<span key={"part-" + i}>{part}</span>
))}
{height && <GradientOverlay onClick={() => setHeight(undefined)} />}
<div ref={ref}>
{parts.map((part, i) => (
<span key={"part-" + i}>{part}</span>
))}
</div>
{showOverlay && <GradientOverlay onClick={expand?.onExpand} />}
</Box>
);
});

View File

@@ -78,6 +78,7 @@ export default function ZapModal({
const onSubmitZap: SubmitHandler<FormValues> = 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 (
<Modal onClose={onClose} {...props}>
<Modal onClose={handleClose} {...props}>
<ModalOverlay />
<ModalContent>
<ModalBody padding="4">