add max height to notes

This commit is contained in:
hzrd149 2023-02-07 17:04:19 -06:00
parent 7f51cd405c
commit 3d2e4f4ae0
9 changed files with 46 additions and 13 deletions

View File

@ -52,7 +52,6 @@
## TODO
- add `client` tag to published events
- add relay selection to global feed
- add button for creating lightning invoice via WebLN
- setup deploy to s3
- make app a valid web share target https://developer.chrome.com/articles/web-share-target/

View File

@ -23,8 +23,9 @@ import { useReadonlyMode } from "../../hooks/use-readonly-mode";
export type NoteProps = {
event: NostrEvent;
maxHeight?: number;
};
export const Note = React.memo(({ event }: NoteProps) => {
export const Note = React.memo(({ event, maxHeight }: NoteProps) => {
const isMobile = useIsMobile();
const readonly = useReadonlyMode();
const { openModal } = useContext(PostModalContext);
@ -52,7 +53,7 @@ export const Note = React.memo(({ event }: NoteProps) => {
</Flex>
</CardHeader>
<CardBody px="2" py="0">
<NoteContents event={event} trusted={following.includes(event.pubkey)} />
<NoteContents event={event} trusted={following.includes(event.pubkey)} maxHeight={maxHeight} />
</CardBody>
<CardFooter padding="2" display="flex" gap="2">
<IconButton

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import {
AspectRatio,
Box,
@ -17,6 +17,7 @@ import { normalizeToHex } from "../../helpers/nip-19";
import { NostrEvent } from "../../types/nostr-event";
import { NoteLink } from "../note-link";
import settings from "../../services/settings";
import styled from "@emotion/styled";
// import { ExternalLinkIcon } from "../icons";
const BlurredImage = (props: ImageProps) => {
@ -166,7 +167,7 @@ const embeds: EmbedType[] = [
regexp: /(https?:\/\/)([\da-z\.-]+\.[a-z\.]{2,6})([\/\w\.-]+\.(svg|gif|png|jpg|jpeg|webp|avif))[^\s]*/im,
render: (match, event, trusted) => {
const ImageComponent = trusted || !settings.blurImages.value ? Image : BlurredImage;
return <ImageComponent src={match[0]} width="100%" maxWidth="30rem" />;
return <ImageComponent src={match[0]} width="100%" maxWidth="30rem" minHeight="20rem" />;
},
name: "Image",
isMedia: true,
@ -264,19 +265,51 @@ function embedContent(content: string, event?: NostrEvent, trusted: boolean = fa
return [content];
}
const GradientOverlay = styled.div`
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: linear-gradient(180deg, rgb(255 255 255 / 0%) 0%, var(--chakra-colors-chakra-body-bg) 100%);
cursor: pointer;
`;
export type NoteContentsProps = {
event: NostrEvent;
trusted?: boolean;
maxHeight?: number;
};
export const NoteContents = React.memo(({ event, trusted }: NoteContentsProps) => {
export const NoteContents = React.memo(({ event, trusted, maxHeight }: NoteContentsProps) => {
const parts = embedContent(event.content, event, trusted ?? false);
const [height, setHeight] = useState(maxHeight);
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);
}
}, [maxHeight, setHeight]);
useEffect(() => {
testHeight();
}, [testHeight]);
return (
<Box whiteSpace="pre-wrap">
<Box
ref={ref}
whiteSpace="pre-wrap"
maxHeight={height}
position="relative"
overflow={maxHeight ? "hidden" : "initial"}
onLoad={() => testHeight()}
>
{parts.map((part, i) => (
<span key={"part-" + i}>{part}</span>
))}
{height && <GradientOverlay onClick={() => setHeight(undefined)} />}
</Box>
);
});

View File

@ -55,7 +55,7 @@ export const DiscoverTab = () => {
return (
<Flex direction="column" gap="2">
{timeline.map((event) => (
<Note key={event.id} event={event} />
<Note key={event.id} event={event} maxHeight={300} />
))}
{loading ? <Spinner ml="auto" mr="auto" mt="8" mb="8" /> : <Button onClick={() => loadMore()}>Load More</Button>}
</Flex>

View File

@ -47,7 +47,7 @@ export const FollowingTab = () => {
<Switch id="show-replies" isChecked={showReplies} onChange={onToggle} />
</FormControl>
{timeline.map((event) => (
<Note key={event.id} event={event} />
<Note key={event.id} event={event} maxHeight={300} />
))}
{loading ? <Spinner ml="auto" mr="auto" mt="8" mb="8" /> : <Button onClick={() => loadMore()}>Load More</Button>}
</Flex>

View File

@ -56,7 +56,7 @@ export const GlobalTab = () => {
</FormControl>
</Flex>
{timeline.map((event) => (
<Note key={event.id} event={event} />
<Note key={event.id} event={event} maxHeight={300} />
))}
{loading ? <Spinner ml="auto" mr="auto" mt="8" mb="8" /> : <Button onClick={() => loadMore()}>Load More</Button>}
</Flex>

View File

@ -32,7 +32,7 @@ const NoteView = () => {
pageContent = (
<>
{parentPosts.map((parent) => (
<Note key={parent.event.id + "-rely"} event={parent.event} />
<Note key={parent.event.id + "-rely"} event={parent.event} maxHeight={200} />
))}
<ThreadPost key={post.event.id} post={post} initShowReplies />
</>

View File

@ -22,7 +22,7 @@ const UserNotesTab = () => {
return (
<Flex direction="column" gap="2" pr="2" pl="2">
{timeline.map((event) => (
<Note key={event.id} event={event} />
<Note key={event.id} event={event} maxHeight={300} />
))}
{loading ? <Spinner ml="auto" mr="auto" mt="8" mb="8" /> : <Button onClick={() => loadMore()}>Load More</Button>}
</Flex>

View File

@ -22,7 +22,7 @@ const UserRepliesTab = () => {
return (
<Flex direction="column" gap="2" pr="2" pl="2">
{timeline.map((event) => (
<Note key={event.id} event={event} />
<Note key={event.id} event={event} maxHeight={300} />
))}
{loading ? <Spinner ml="auto" mr="auto" mt="8" mb="8" /> : <Button onClick={() => loadMore()}>Load More</Button>}
</Flex>